25

如果我的模型包含带有 RadioSelect 小部件的 ChoiceField,如何在模板中单独呈现单选按钮?

假设我正在构建一个 Web 应用程序,它允许公司的新员工选择他们想要的桌面计算机类型。这是相关模型:

class ComputerOrder(forms.Form):
    name = forms.CharField(max_length=50)
    office_address = forms.Charfield(max_length=75)
    pc_type = forms.ChoiceField(widget=RadioSelect(), choices=[(1, 'Mac'), (2, 'PC')])

在模板上,如何渲染Mac 选择按钮?如果我这样做,它会呈现所有选择:

{{ form.pc_type  }}

我有点天真地尝试了这个,但它没有产生任何输出:

{{ form.pc_type.0 }}

(我在这里发现了一些类似的问题:

在 Django 表单中,如何呈现单选按钮以便在页面上分隔选项?
Django 表单:如何在 Django 表单中迭代一个字段的选择

但我不觉得他们有很好的答案。有没有办法让老问题复活?)

4

4 回答 4

51

Django 1.4+允许您迭代a 中的选择RadioSelect,以及

{% for choice in form.pc_type %}
  {{ choice.choice_label }}
  <span class="radio">{{ choice.tag }}</span>
{% endfor %}

我不确定此更改是否允许您使用您描述的语法 ( {{ form.pc_type.0 }}) — 如果没有,您可以使用for上面的循环和类似{% if forloop.counter0 == 0 %}.

如果您绑定到 Django < 1.4,您可以render()按照建议覆盖该方法,或者使用稍微更详细但不太复杂的选项在模板中自己构建表单字段:

 {% for choice in form.pc_type.field.choices %}
   <input name='{{ form.pc_type.name }}' 
     id='{{ form.pc_type.auto_id }}_{{ forloop.counter0 }}' type='radio' value='{{ choice.0 }}'
     {% if not form.is_bound %}{% ifequal form.pc_type.field.initial choice.0 %} checked='checked' {% endifequal %}
   {% else %}{% ifequal form.pc_type.data choice.0 %} checked='checked' {% endifequal %}{% endif %}/>
   <label for='{{ form.pc_type.auto_id }}_{{ forloop.counter0 }}'>{{ choice.1 }}</label>
 {% endfor %}

choice.0并且是双元组choice.1中的第一项和第二项)choices

于 2012-07-09T17:18:29.740 回答
6

单个无线电输入的呈现由RadioSelect小部件的render方法处理。如果您想要不同的渲染, subclass RadioSelect,相应地更改render方法,然后将您的子类用作字段的小部件。

于 2012-04-19T21:42:22.963 回答
4

我认为简单地查看选择字段的 for 循环中可用的内容将告诉人们他们需要知道什么。例如,我需要该值来设置围绕选项范围的类(用于颜色等):

<div>
    {% for radio_input in form.role %}
        {# Skip the empty value #}
        {% if radio_input.choice_value %}
            <span class="user-level {{ radio_input.choice_value }}">{{ radio_input }}</span>
        {% endif %}
    {% endfor %}
</div>

如您所见,有几个属性使您不必使用序数。

模板内的 PyCharm 调试

于 2013-04-12T22:19:37.343 回答
2

在 Django 2.0+ 中,您可以子类forms.RadioSelect化并“简单地”指定用于呈现单选字段的模板:

class SlimRadioSelect(forms.RadioSelect):
    template_name = 'includes/slim_radio.html'

其中slim_radio.html包含由默认 RadioSelect 小部件template_name组合和option_template_name使用的修订版本。

请注意,默认的 RadioSelect 小部件模板是低级渲染,由多层模板组成:包含、条件和循环逻辑标签比比皆是。

当您四处挖掘packages/django/forms/templates/django/forms/widgets/input.html以获取您需要的东西时,您就会知道您已经到了。

覆盖默认小部件模板的另一个奇怪之处是您必须调用TemplatesSetting渲染器,否则您的子类将无法 slim_radio.html在项目的通常可访问的模板路径中找到。

要覆盖 RadioSelect 的仅本地模板路径查找:

  1. 添加'django.forms'到您的INSTALLED_APPS;

  2. 添加FORM_RENDERER = 'django.forms.renderers.TemplatesSetting'到您的settings.py.

这一切似乎都比应该的要难,但那是框架。祝你好运。

于 2020-04-04T18:38:42.637 回答