Django 模板中的逻辑问题
假设这是一个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 个回答
只需要调整你的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 %}
附注:你的问题没有清楚地说明你想要什么。我做了一些合理的假设。如果你想要的内容不一样,请更新你的问题。
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 %}
这个问题的真正答案是这样的:
这种逻辑不应该放在模板里。你可以在把数据传给模板之前先处理好这些数据,这样就不需要用那个(故意设计得不太灵活的)模板引擎来处理了。
我觉得你这样做是不对的。我的意思是,Django有很好的表单API,为什么要直接渲染输入呢?有人可能会说,Django的表单API不够灵活,但对于这个特定的需求来说,它绝对是足够的。
再强调一下——这种逻辑不应该放在展示层。所以不要把它放在那里,这样会给你带来麻烦。实际上,它已经给你带来了麻烦。