How to get the label of a choice in a Django forms ChoiceField?
Asked Answered
U

10

83

I have a ChoiceField, now how do I get the label when I need it?

class ContactForm(forms.Form):
     reason = forms.ChoiceField(choices=[("feature", "A feature"),
                                         ("order", "An order")],
                                widget=forms.RadioSelect)

form.cleaned_data["reason"] only gives me the feature or order values or so.

Undernourished answered 17/4, 2009 at 18:43 Comment(6)
I think you may need to reconsider which answer is the accepted one..Sushi
@Dan: Why? Which one do you prefer?Undernourished
@Undernourished The one with the most up-votes is the more django-centric one which requires less code be written on a per-model basis.Mun
@JackM. if you mean @shacker's, it doesn't actually answer the question. get_FOO_display applies to django.db.models.ChoiceField, not django.forms.ChoiceField. The currently-accepted answer (by Andrés) is the best one can do as of Django 1.5, I believe.Behl
The accepted answer also works in more cases. For example if you query the FOO table, but want a dict rather than a model (using FOO.objects.values()), it will work with tiny adjustments. @shacker's answer works only for full-fledged models.Chessa
Weird enough, Django considers in this example feature and order as values, and A feature, An order as labels. SourceAlaska
M
98

This may help:

reason = form.cleaned_data['reason']
reason = dict(form.fields['reason'].choices)[reason]
Maisonette answered 29/9, 2011 at 17:14 Comment(1)
Django allows grouped choices. If you have those, this won't work.Zealot
G
172

See the docs on Model.get_FOO_display(). So, should be something like :

ContactForm.get_reason_display()

In a template, use like this:

{{ OBJNAME.get_FIELDNAME_display }}
Guarani answered 18/4, 2009 at 3:28 Comment(4)
But it's not a model, it's a form.Undernourished
Yep. That only holds true for Django models. Forms do not emulate this behavior (though now I'm wishing they did)...Dutybound
This is great for models. Thank you for the hint. I suppose it still needs to be done differently for forms.Delineator
Had the same problem, but with a ModelForm. Hence, {{form.instance.get_FIELDNAME_display}} worked like charm for me.Shenitashenk
M
98

This may help:

reason = form.cleaned_data['reason']
reason = dict(form.fields['reason'].choices)[reason]
Maisonette answered 29/9, 2011 at 17:14 Comment(1)
Django allows grouped choices. If you have those, this won't work.Zealot
J
29

This the easiest way to do this: Model instance reference: Model.get_FOO_display()

You can use this function which will return the display name: ObjectName.get_FieldName_display()

Replace ObjectName with your class name and FieldName with the field of which you need to fetch the display name of.

Johnniejohnny answered 5/3, 2012 at 21:40 Comment(2)
NB the number of times you mention "model" in your answer (3) and the number of times @Undernourished mentioned it in the question (0).Behl
chosen_label = form.instance.get_FOO_display() is working oneOverbold
R
9

If the form instance is bound, you can use

chosen_label = form.instance.get_FOO_display()
Ritualism answered 7/4, 2012 at 2:18 Comment(1)
This would only work for ModelForm, the question does not mention that.Tomblin
M
4

Here is a way I came up with. There may be an easier way. I tested it using python manage.py shell:

>>> cf = ContactForm({'reason': 'feature'})
>>> cf.is_valid()
True
>>> cf.fields['reason'].choices
[('feature', 'A feature')]
>>> for val in cf.fields['reason'].choices:
...     if val[0] == cf.cleaned_data['reason']:
...             print val[1]
...             break
...
A feature

Note: This probably isn't very Pythonic, but it demonstrates where the data you need can be found.

Mortgage answered 17/4, 2009 at 20:6 Comment(1)
Is there any word on if this sort of thing is part of core now? It's unfathomable that this isn't in the form API yet I have a hard time googling for a better solution.Amelita
Y
4

OK. I know this is very old post, but reading it helped me a lot. And I think I have something to add.

The crux of the matter here is that the the model method.

ObjectName.get_FieldName_display()

does not work for forms.

If you have a form, that is not based on a model and that form has a choice field, how do you get the display value of a given choice.

Here is some code that might help you.

You can use this code to get the display value of a choice field from a posted form.

display_of_choice = dict(dateform.fields['fieldnane'].choices)[int(request.POST.get('fieldname'))]

the 'int' is there on the basis the choice selection was a integer. If the choice index was a string then you just remove the int(...)

Yalu answered 23/3, 2020 at 1:7 Comment(2)
Any idea how to display the display value of a given choice in a template? I.E. Doesn't seem like {{form.get_fieldchoice_display}} worksYippie
There is my answer above, plus there are number of valid answers in subsequent posts. All give options at you disposal, if you want a specific answer, then post your actual code and we can give you specific answer, happy to do so.Yalu
D
3

You can have your form like this:

#forms.py
CHOICES = [('feature', "A feature"), ("order", "An order")]
class ContactForm(forms.Form):
     reason = forms.ChoiceField(choices=CHOICES,
                                widget=forms.RadioSelect)

Then this would give you what you want:

reason = dict(CHOICES)[form.cleaned_data["reason"]]
Dniren answered 9/5, 2012 at 11:20 Comment(0)
C
1

Im using @Andrés Torres Marroquín way, and I want share my implementation.

GOOD_CATEGORY_CHOICES = (
    ('paper', 'this is paper'),
    ('glass', 'this is glass'),
    ...
)

class Good(models.Model):
    ...
    good_category = models.CharField(max_length=255, null=True, blank=False)
    ....

class GoodForm(ModelForm):
    class Meta:
        model = Good
        ...

    good_category = forms.ChoiceField(required=True, choices=GOOD_CATEGORY_CHOICES)
    ...


    def clean_good_category(self):
        value = self.cleaned_data.get('good_category')

        return dict(self.fields['good_category'].choices)[value]

And the result is this is paper instead of paper. Hope this help

Cliftonclim answered 26/2, 2019 at 9:48 Comment(0)
K
1

confirm that Ardi's and Paul's response are best for forms and not models. Generalizing Ardi's to any parameter:

    class AnyForm(forms.Form):
        def get_field_name_display(self, field_name):
            return dict(self.fields[field_name].choices[self.cleaned_data[field_name]]

Or put this method in a separate class, and sub-class it in your form

class ChoiceFieldDisplayMixin:
    def get_field_name_display(self, field_name):
        return dict(self.fields[field_name].choices[self.cleaned_data[field_name]]


class AnyCustomForm(forms.Form, ChoiceFieldDisplayMixin):
    choice_field_form = forms.ChoiceField(choices=[...])

Now call the same method for any Choice Field:

form_instance = AnyCustomForm()
form_instance.is_valid()
form_instance.get_field_name_display('choice_field_form')
Kbp answered 12/5, 2022 at 0:40 Comment(1)
now mix it up with a metaclass, and you'll end up with the get_FOO_display thing you can easily use in templates, as you'd do with models...isn't this what everybody wants?Minsk
A
0

I think maybe @webjunkie is right.

If you're reading from the form from a POST then you would do

def contact_view(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            contact = form.save()
            contact.reason = form.cleaned_data['reason']
            contact.save()
Alphonsoalphonsus answered 25/10, 2010 at 22:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.