Django模板中的逻辑问题

时间:2009-11-22 15:34:45

标签: python django templates django-templates

使用Django模板的这一部分。 regs是Reg对象的列表。 Reg.editable是一个BooleanField。 我想在列表中为每个元素渲染一个单选按钮。如果r.editable为False,则必须禁用单选按钮:

{% for r in regs %}
<input type="radio" value="{{ forloop.counter }}"
{% if forloop.first %}checked="checked"{% endif %}
{% if not r.editable %}disabled="disabled"{% endif %}/> 
{% endfor %}

如您所见,我正在使用forloop.first检查第一个单选按钮,但这有问题!如果第一个元素有editable == False怎么办?第一个单选按钮将被禁用并加载。如果用户提交“表单”,我将收到一个不期望的值。

我清楚这个问题吗?如何重写此模板以在选中FIRST ENABLED单选按钮时进行渲染?

由于

5 个答案:

答案 0 :(得分:2)

Djangos模板语言并没有给你很多关于模板中逻辑的方法(如果你想改变它,我听说过关于Jinja2的积极的事情)。还有"Smart" {% if %}标签,它增加了一些功能,顺便提一下,它被包含在Django 1.2中。

至于解决这个问题,我很可能将逻辑移到视图上。 (免责声明:没有时间测试此代码段,但它应该提供一般的想法)

def my_view(request, *args, **kwargs):

    # QuerySet is fetched however it's done...
    regs = Regs.objects.all()

    # Wrap regs in display information    
    checked = False
    radio_buttons = []

    for r in regs:
        if r.editable:
            if not checked:
                 radio_buttons.append( { 'checked':True, 'enabled':True, 'object':r } )
                 # Set to true once
                 checked = True
            else:
                 radio_buttons.append( { 'checked':False, 'enabled':True, 'object':r } )
        else:
            radio_buttons.append( { 'checked':False, 'enabled':False, 'object':r } )          

    # Then pass in radio_buttons for the value of regs down here
    render_to_whatever(..., { 'regs':radio_buttons } )

在这种情况下,我们已经包装了QuerySet,它将为我们的模板提供有关渲染的更多细节。模板现在变得“愚蠢”。

{% for r in regs %}
    <input type="radio" value="{{ forloop.counter }}"
    {% if r.checked %}checked="checked"{% endif %}
    {% if not r.enabled %}disabled="disabled"{% endif %}/> 
    {% comment %} To access the original object use: {{ r.object }} {% endcomment %}
{% endfor %}

答案 1 :(得分:1)

调整 if

{% for r in regs %}
    {% if forloop.first %}
        <input type="radio" value="{{ forloop.counter }}" checked="checked"/>
    {% else %}
        {% if not r.editable %}
            <input type="radio" value="{{ forloop.counter }}" disabled="disabled"/> 
        {% endif %}
    {% endif %}
{% endfor %}
PS:你的问题没有清楚地解释你想要什么。我做了一些合理的假设。如果您想要的是其他内容,请更新问题。

答案 2 :(得分:1)

此问题的真实答案如下:

这种逻辑在模板中没有位置。您可以在将上下文传递给模板之前对其进行预处理,从而无需使用(故意)残缺的模板引擎逻辑来实现此目的。

在我看来,你所做的是错的。我的意思是,django有完美的形式api,为什么直接渲染输入呢?有些人可能会争辩说,django的形式api是不灵活的,但对于这个特定的需要,它无疑是足够的。

并重申 - 这种逻辑不属于表示层。所以不要把它放在那里,它会咬你。事实上它已经做到了。

答案 3 :(得分:0)

类似于T. Stone在视图中执行此逻辑的答案,您可以添加一个新的模板变量来指示第一个已检查的无线电:

def my_view(request, *args, **kwargs):
  regs = Regs.objects.all()
  checked_index = None
  for i, reg in enumerate(regs):
    if reg.enabled:
      checked_index = i
      break
  # pass checked_index into the template...

模板:

{% for r in regs %}
  {% ifequal forloop.counter0 checked_index %}
    <input type="radio" value="{{ forloop.counter }}" checked="checked"/>
  {% else %}
    <input type="radio" value="{{ forloop.counter }}" {% if not r.editable %}disabled="disabled"{% endif %}/> 
  {% endif %}
{% endfor %}

答案 4 :(得分:0)

与BecomeGuru类似但解决问题:

{% for r in regs %}
    {% if not r.editable %}
        <input type="radio" value="{{ forloop.counter }}" disabled="disabled"/>     
    {% else %}
        {% if forloop.first %}
            <input type="radio" value="{{ forloop.counter }}" checked="checked"/>
        {% endif %}
    {% endif %}
{% endfor %}

首先检查r是否可编辑,然后检查它是否是第一个。 问候。