Django模板 - 停止处理模板

时间:2011-12-09 16:15:58

标签: python django

我正在寻找在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或return。

模板语言中有没有办法做类似的事情(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 个答案:

答案 0 :(得分: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 %}

答案 1 :(得分:3)

您可以使用jinaj2来模板化该视图(或整个项目),它支持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

答案 2 :(得分:2)

虽然我认为@burhan's方法更好,但您也可以通过使用自定义标记来执行您想要做的事情,该标记将上下文变量设置为布尔值,而最外层的其他部分也可以转换为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,具体取决于参数。

答案 3 :(得分:1)

今天我遇到了同样的问题。 我发现这个标签 {%verbatim%} {%endverbatim%} 。这适用于Django1.5 + 一个例子:

  {% verbatim %} 
  <div class="entry">
    <h1>{{ title }}</h1>
    <div class="body">
      {{ body }}
    </div>
  </div>
  {% endverbatim %}

您还可以在下方查看更多详情: