Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django order choice field

I've been struggling with Django choice fields in form. I have choices in my forms.py and a radio choice field.

DURATION_CHOICES = {
    (1, '30'),
    (2, '45'),
    (3, '60'),
    (4, '75'),
    (5, '90'),
    (6, '105'),
    (7, '120+'),
}

duration = forms.ChoiceField(choices=DURATION_CHOICES, widget=forms.widgets.RadioSelect, label_suffix="", label="Trainingsdauer in Minuten",)

However when I open the form to create a new training session, the duration radio select field is randomly ordered, i.e. 105 is in the list before 45. The order even changes from testing devices to another

I have the very same problem with choice fields from models.py

I have already ordered my choices but how do I get the ordered choice list in my form?

like image 269
Matthias Hügli Avatar asked May 21 '18 13:05

Matthias Hügli


People also ask

How do you define choice fields in Django?

Choices can be any sequence object – not necessarily a list or tuple. The first element in each tuple is the actual value to be set on the model, and the second element is the human-readable name. Let us create a choices field with above semester in our django project named geeksforgeeks.

How do you use choices in Django?

ChoiceField in Django Forms is a string field, for selecting a particular choice out of a list of available choices. It is used to implement State, Countries etc. like fields for which information is already defined and user has to choose one. It is used for taking text inputs from the user.

How do I make a field optional in Django?

Enter Venue Name, Address and Zip/Post Code in the blank form, but leave the Contact Phone, Web Address and Email Address fields blank. Click “Save”. Your screen should look something like Figure 7.5.


1 Answers

I think this is more a problem with the collection you use. You here use curly quotes ({}). This is a set. A set us an unordered collection of hashable elements that occur zero or one time. But as said, the collection is unordered. This means there are no guarantees if you enumerate over the collection in what order you will retrieve it.

Use a list or tuple

I think you better use a list or a tuple here, which is an ordered collection of elements. For lists you can use square brackets ([]), for tuples one uses round brackets (()):

DURATION_CHOICES = [
    (1, '30'),
    (2, '45'),
    (3, '60'),
    (4, '75'),
    (5, '90'),
    (6, '105'),
    (7, '120+'),
]

Sort the collection before you pass it as an argument

If you want to keep using the set, we can convert it to a list before adding it to the field. We can for instance use sorted(..) to sort it based on the first item of the tuple:

from operator import itemgetter

duration = forms.ChoiceField(
    choices=sorted(DURATION_CHOICES, key=itemgetter(0)),
    widget=forms.widgets.RadioSelect,
    label="Trainingsdauer in Minuten",
)

Note however that if you make changes to the DURATION_CHOICES set, those changes will not reflect in the ChoiceField, since we here made a shallow copy to a list.

like image 140
Willem Van Onsem Avatar answered Oct 05 '22 13:10

Willem Van Onsem