Django 模板中的逻辑问题

0 投票
5 回答
1183 浏览
提问于 2025-04-15 16:15

假设这是一个Django模板的一部分。regs是一个包含Reg对象的列表。Reg.editable是一个布尔值字段,表示这个对象是否可以编辑。

我想为列表中的每个元素渲染一个单选按钮。如果某个元素的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,那么第一个单选按钮就会被渲染为禁用状态并且是选中的。这样一来,如果用户提交了“表单”,我就会收到一个意想不到的值。

我说的这个问题你明白了吗?我该如何重写这个模板,以便让第一个可用的单选按钮被选中呢?

谢谢

5 个回答

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 %}

附注:你的问题没有清楚地说明你想要什么。我做了一些合理的假设。如果你想要的内容不一样,请更新你的问题。

2

Django的模板语言在模板中提供的逻辑功能不多。如果你想要更多的功能,可以考虑使用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

这个问题的真正答案是这样的:

这种逻辑不应该放在模板里。你可以在把数据传给模板之前先处理好这些数据,这样就不需要用那个(故意设计得不太灵活的)模板引擎来处理了。

我觉得你这样做是不对的。我的意思是,Django有很好的表单API,为什么要直接渲染输入呢?有人可能会说,Django的表单API不够灵活,但对于这个特定的需求来说,它绝对是足够的。

再强调一下——这种逻辑不应该放在展示层。所以不要把它放在那里,这样会给你带来麻烦。实际上,它已经给你带来了麻烦。

撰写回答