In Django when using the choices parameter on a form field the format passed in must be as follows:
# within your models.Model class... STUDENT_TYPE_CHOICES = ( ('0', 'freshman'), ('1', 'sophomore'), ('2', 'junior'), ('3', 'senior'), ) student_type = models.CharField(max_length=1, choices=STUDENT_TYPE_CHOICES)
This means elsewhere in your code if you want to specify a choice field value, you’d have to enter the first slot of the tuple’s value, e.g.:
junior_students = Student.objects.filter(student_type='2')
This is pretty terrible since it’s hardcoded in our source, possibly over many files.
How to fix this mess:
In my project I added common/utils.py containing the following:
from enum import Enum class ChoiceEnum(Enum): @classmethod def choices(cls): return tuple((i.name, i.value) for i in cls)
That’s the hard work over.
Now when you create your field with choices:
from common.utils import ChoiceEnum class StudentTypes(ChoiceEnum): freshman = 0 sophomore = 1 junior = 2 senior = 3 # within your models.Model class... class Student(models.Model): student_type = models.CharField(max_length=1, choices=StudentTypes.choices())
Now if we need to access StudentTypes from elsewhere in our source code, we can simply:
junior_students = Student.objects.filter(student_type=StudentTypes.junior.value)
That’s it. If anyone knows of a nicer way feel free to comment below.