Django forms ChoiceField and custom HTML output...

Published at Jan. 6, 2011 | Tagged with: , , , ,

... or what to do in case that you need a special design for your choice fields

The problem: Few posts ago I talked(wrote) about Django forms ChoiceField and with dynamic values and now it is time to take a look at the front end and how we display these values to the user. I will use the code from that post:

class MyForm(forms.Form):
    my_choice_field = forms.ChoiceField(choices=MY_CHOICES)
By default Django provide us with a simple drop-down list as visual representation of the choice field. Just create and instance of the form in your view, pass it in the context:
def my_view(request):
    form = MyForm()
    return render_response('template.html',{'form': form})
and then display it in the template using {{form.my_choice_field}}. Speciality: For most cases this drop-down works just fine but sometimes this is not enough. Lets say that instead of drop-down list we need a radio buttons. There are two ways to achieve this - using a custom widget or playing with the template tags and the ChoiceField object. The first solutions is more suitable if you have a repeatable interface for several fields. In my case this was field specific so I chose the second one as faster for implementation. Solution: You can access the field object and its choices calling the field respectively field.choices properties of the form element in the template. Here is an example
{% for choice in form.my_choice_field.field.choices %}
    <input type="radio" name="my_choice_field" value="{{choice.0}}"
      {% ifequal choice.0 %} 
      {% endifequal %}/>
    <label for="">{{choice.1}}</label>
{% endfor %}

This allows you to specify custom styles/HTML for every element and also to distinct first and last elements using forloop.first and forloop.last - for more information you can check Django documentation about the for template tag

Final words: I did not have the chance to measure the speed difference between these two methods I mentions but I intend to post a also an example of the first one(using custom widget) and a "benchmark" between them both. If someone has already done this please post the results and your opinion about this.