You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Django模板标签同时输出原代码与渲染结果?

实现Django示例模板标签的方案

核心思路

要同时拿到标签内的原始未渲染文本和渲染后的结果,得绕开Django默认的模板解析逻辑——普通标签内容会被解析成StaticNode这类节点,没法直接获取原始字符串。我们需要在解析阶段就保存原始文本,同时保留解析后的节点用于生成渲染结果。

具体实现步骤

1. 自定义模板标签解析器

模仿verbatim标签的特殊解析逻辑,同时保留原始文本和可渲染节点:

from django import template
from django.template.base import Parser

register = template.Library()

class ExampleNode(template.Node):
    def __init__(self, raw_text, rendered_nodes):
        self.raw_text = raw_text
        self.rendered_nodes = rendered_nodes

    def render(self, context):
        # 生成渲染后的内容
        rendered_content = self.rendered_nodes.render(context)
        # 返回对比展示的HTML结构
        return f"""
        <div class="demo-example">
            <h4>原始模板代码</h4>
            <pre>{template.defaultfilters.escape(self.raw_text)}</pre>
            <h4>渲染结果</h4>
            <pre>{template.defaultfilters.escape(rendered_content)}</pre>
        </div>
        """

@register.tag(name='example')
def do_example(parser, token):
    # 提取{% example %}到{% endexample %}之间的原始文本
    raw_text = parser.get_until('endexample')
    # 重置解析位置,重新解析这段文本为可渲染节点
    temp_parser = Parser(parser.source, parser.origin)
    # 定位到当前标签后的token区间
    start_idx = parser.tokens.index(token) + 1
    end_idx = start_idx + raw_text.count('\n') + 1
    temp_parser.tokens = parser.tokens[start_idx:end_idx]
    rendered_nodes = temp_parser.parse(('endexample',))
    # 跳过结束标签
    temp_parser.next_token()
    return ExampleNode(raw_text.strip(), rendered_nodes)

2. 关键细节说明

  • 获取原始文本:parser.get_until('endexample')直接提取标签内的原始字符串,这是verbatim标签能保留纯文本的核心逻辑,避免内容被提前解析。
  • 重新解析生成节点:把原始文本传入临时解析器,生成正常的可渲染节点列表,以此得到最终渲染结果。
  • 转义处理:用escape过滤器处理文本,避免HTML标签被浏览器解析,保证代码原样展示。

3. 模板使用示例

{% example %}
import * as fancy from "{% static 'jslib/fancy.min.js' %}";
{% endexample %}

输出会同时展示原始的模板代码,以及渲染后的import * as fancy from "/static/jslib/fancy.min.js";。

简化替代方案

如果不想操作解析器,也可以手动重复内容:

<div class="demo-example">
    <h4>原始模板代码</h4>
    <pre>{% verbatim %}import * as fancy from "{% static 'jslib/fancy.min.js' %}";{% endverbatim %}</pre>
    <h4>渲染结果</h4>
    <pre>{{ "import * as fancy from \"{% static 'jslib/fancy.min.js' %}\";"|safe }}</pre>
</div>

但这种方式需要重复编写内容,不如自定义标签高效。

内容的提问来源于stack exchange,提问作者run_the_race

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 01:35:27