Flobin Flobin - 1 year ago 130
Python Question

Django rendering display name of choice field in form

tl;dr: How do I make a form output the ‘nice’ name of the choices in a model?

I have a Django model with choices, defined like this:

class City(models.Model):
(AMSTERDAM, 'Amsterdam'),
(ROTTERDAM, 'Rotterdam'),
(THE_HAGUE, 'The Hague'),
(UTRECHT, 'Utrecht'),
name = models.CharField(

In forms.py, the widgets are defined like this:

class ArticleForm(ModelForm):
class Meta:
model = Article
fields = ['title', 'text', 'categories', 'city']
widgets = {'title': forms.TextInput(attrs={
'placeholder': 'Enter a descriptive title'}),
'text': forms.Textarea(attrs={'placeholder': 'The article'}),
'categories': forms.CheckboxSelectMultiple(),
'city': forms.RadioSelect(),

The form itself is rendered manually (although the same effect happens with just

<form action="{% url 'article-submit' %}" method="POST">
{% csrf_token %}
{{% for field in form %}
<fieldset class="article-form__field">
{% if field.name = "categories"%}
{{ field.label_tag }}
<ul id={{ field.auto_id }}>
{% for checkbox in field %}
<label for="{{ checkbox.id_for_label }}">
{{ checkbox.choice_label }}
{{ checkbox.tag }}
{% endfor %}
{% elif field.name = "city" %}
{{ field.label_tag }}
<ul id={{ field.auto_id }}>
{% for radio in field %}
<label for="{{ radio.id_for_label }}">
{{ radio.choice_label }}
{{ radio.tag }}
{% endfor %}
{% else %}
{{ field.label_tag }} {{ field }}
{% endif %}
{% endfor %}}
<fieldset class="article-form__field">
<input class="button" type="submit" value="submit">

However the output is not Amsterdam, but AMS:

<fieldset class="article-form__field">

<label for="city_0">City:</label>
<ul id=city>

<label for="city_0">
<input checked="checked" id="city_0" name="city" type="radio" value="" />

<label for="city_1">
<input id="city_1" name="city" type="radio" value="1" />

In other templates, I could do this:
, to get the full name. How do I do this in the form?

full code is here

Answer Source

I got the following answer from reddit user roambe:

Since city is a foreign key, Django will use the __str__ (or __unicode__) method of the City model for the choice label. This should make it start behaving like you want to (substitute for unicode if needed):

def __str__(self):
    return self.get_name_display()