Answer a question

If I have a model that contains a ChoiceField with a RadioSelect widget, how can I render the radio buttons separately in a template?

Let's say I'm building a web app that allows new employees at a company to choose what kind of computer they want on their desktop. This is the relevant model:

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')])

On the template, how do I render just the Mac choice button? If I do this, it renders all the choices:

{{ form.pc_type  }}

Somewhat naively I tried this, but it produced no output:

{{ form.pc_type.0 }}

(I found a few similar questions here on SO:

In a Django form, how do I render a radio button so that the choices are separated on the page?
Django Forms: How to iterate over a Choices of a field in Django form

But I didn't feel like they had good answers. Is there a way to resurrect old questions?)

Answers

Django 1.4+ allows you to iterate over the choices in a RadioSelect, along with the lines of

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

I'm not sure if this change allows you to use the syntax you describe ({{ form.pc_type.0 }}) — if not, you could work around this limitation with the for loop above and a tag like {% if forloop.counter0 == 0 %}.

If you're tied to Django < 1.4, you can either override the render() method as suggested or go with the slightly-more-verbose-but-less-complicated option of building up the form field yourself in the template:

 {% 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 and choice.1 are the first and second items in your choices two-tuple)

Logo

Python社区为您提供最前沿的新闻资讯和知识内容

更多推荐