Django模板 - 停止处理模板

4 投票
4 回答
1416 浏览
提问于 2025-04-17 08:03

我想找一种方法来清理Django中的模板。一个简单的解决办法是把这个模板拆分成多个,但我们不想这样做。

我们基本上有以下内容:

{%if data.some_state %}
    Display some markup
{% else %}
   {%if data.some_state_2 %}
       State 2 different html view 
   {% else %}
        {%if data.process_data %}
           Display some list of data
        {% else %}
           No Data to display!
       {% endif %} <!-- if data.process_data-->
   {% endif %} <!-- if data.some_state_2 -->
{% endif %} <!-- if data.some_state -->

这看起来非常混乱,难以阅读。如果我能把它放在一个“函数”里,我会使用if/else if或者返回值。

在模板语言中,有没有办法做类似的事情(stop_processing_template可以告诉模板我们完成了……):

{%if data.some_state %}
    Display some markup
{% endif %}
{% django_stop_processing_template %}


{%if data.some_state_2 %}
       State 2 different view
{% endif %}
{% django_stop_processing_template %}

{%if data.process_data %}
           Display some list of data
{% endif %}
{% django_stop_processing_template %}

 No data provided !

4 个回答

2

虽然我觉得 @burhan的 方法更好,但你也可以通过使用一个自定义标签来实现你想要的功能。这个自定义标签会设置一个上下文变量为布尔值(也就是真或假),然后最外层的 else 部分也可以改成 if 标签。

#Set a context variable nodata to True 
{% setnodata True %}  
{%if data.some_state %}
    Display some markup
    #Set context variable nodata to False  
    {% setnodata False %}
{% endif %}

{%if data.some_state_2 %}
    State 2 different view
    #Set context variable nodata to False  
    {% setnodata False %} 
{% endif %}

{%if data.process_data %}
    Display some list of data
    #Set context variable nodata to False  
    {% setnodata False %}
{% endif %}

{% if nodata %}
    No data provided !
{ % endif %}

这个 setnodata 自定义标签会根据传入的参数,把上下文变量 nodata 设置为真(True)或假(False)。

4

我不太清楚你处理模板的逻辑是怎样的,但有个更简单的方法可以实现你的逻辑,那就是写一个自定义标签,这个标签可以接收你的参数,然后只返回与你的变量相关的HTML内容。这样你就可以去掉那些复杂的if/else循环,直接用一个简单的{% do_stuff %}标签来替代。

编辑

这里有一个非常简单的实现,给你一些关于逻辑如何运作的概念。

首先,你需要为每种变化创建模板,并把它们存放在Django可以找到的地方。

然后,写一个简单的标签,用来渲染你想要的具体模板(这个是未测试的伪代码):

from django import template
from django.db.models import get_model
register = template.Library()

class ProcessData(template.Node):
    def __init__(self, var_name):
        self.obj = get_model(*var_name.split('.'))
    def render(self, context):
        if self.obj.some_state:
           t = template.loader.get_template('some_markup_template.html')
           result = 'something'
        else:
           if self.obj.some_state_2:
              t = template.loader.get_template('some_different_html_view.html')
              result = 'something'
       else:
          if self.obj.process_data:
             t = template.loader.get_template('some_list_data.html')
             result = 'something'
          else:
             t = template.loader.get_template('no_data.html')
             result = 'something'
        return t.render(Context({'result': result}, autoescape=context.autoescape))

@register.tag
def process_data(parser, token):
    try:
        tag_name, arg = token.contents.split(None, 1)
    except ValueError:
        raise template.TemplateSyntaxError("%r tag requires arguments" % token.contents.split()[0])
    return ProcessData(arg)

最后,在你的模板中:

{% load my_tags %}
{% process_data data.mymodel %}
3

你可以使用 jinja2 来处理这个视图的模板(或者整个项目),它支持 if/elif/else 这样的条件判断:

{% if data.some_state %}
    Display some markup
{% elif data.some_state_2 %}
    State 2 different view
{% elif data.process_data %}
    Display some list of data
{% endif %}

有几个不同的工具包可以让你在 Django 项目中轻松使用 jinja2,我用过 coffindjinja 这两个。

撰写回答