【问题标题】:Problem with logic in Django templateDjango模板中的逻辑问题
【发布时间】:2010-12-19 05:46:28
【问题描述】:

假设 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 来检查第一个单选按钮,但这有问题!如果第一个元素具有可编辑 == False 怎么办?第一个单选按钮将被禁用并选中。如果随后用户提交“表单”,我将收到一个未预期的值。

我是否清楚这里的问题?如何重写此模板以呈现为选中的 FIRST ENABLED 单选按钮?

谢谢

【问题讨论】:

  • 顺便说一句,我没有使用孔 Django,只是模板引擎,所以我无法将此逻辑移至视图:)

标签: python django templates django-templates


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

    这个问题的真实答案如下:

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

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

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

    【讨论】:

      【解决方案3】:

      只需调整你的ifs

      {% 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:你的问题没有清楚地解释你想要什么。我做了一些合理的假设。如果您想要的是其他内容,请更新问题。

      【讨论】:

      • 这样解决了第一个radio没有被(勾选和禁用)的问题,但是如果第一个radio应该是(disabled并且不勾选)呢?
      【解决方案4】:

      类似于 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 %}
      

      【讨论】:

        【解决方案5】:

        类似于成为大师,但解决你的问题:

        {% 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 是否可编辑,然后检查它是否是第一个。 问候。

        【讨论】:

          猜你喜欢
          • 2012-02-27
          • 2018-12-30
          • 2013-07-25
          • 1970-01-01
          • 1970-01-01
          • 2013-01-24
          • 2019-10-06
          • 2010-10-13
          • 2015-05-05
          相关资源
          最近更新 更多