Как отображать отдельные кнопки переключателя в Django?
Если у меня есть модель, содержащая ChoiceField с виджетами RadioSelect, как я могу отображать переключатели отдельно в шаблоне?
Скажем, я создаю веб-приложение, которое позволяет новым сотрудникам компании выбирать, какой компьютер они хотят на своем рабочем столе. Это соответствующая модель:
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 }}
(Я нашел несколько похожих вопросов здесь на SO:
В форме Django, как мне отобразить переключатель, чтобы выбор был разделен на странице?
Django Forms: как перебирать выбор поля в форме Django
Но я не чувствовал, что у них хорошие ответы. Есть ли способ воскресить старые вопросы?)
Ответы
Ответ 1
Django 1.4+ позволяет выполнять итерацию по выбору в 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
двухкортеже)
Ответ 2
Обработка отдельных радиовходов осуществляется с помощью метода RadioSelect
widget render
. Если вы хотите другой рендеринг, подкласс RadioSelect
, соответствующим образом измените метод render
, а затем используйте свой подкласс в качестве виджета поля.
Ответ 3
Я думаю, что просто глядя на то, что доступно внутри цикла 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 Debugging Inside a Template]()