Override Django Form Choices

# models.py
class Employee(models.Model):
    INTERNSHIP, FULL_TIME, PART_TIME = range(3)
    EMPLOYEE_STATUS_CHOICES = (
        (INTERNSHIP, 'Internship'),
        (FULL_TIME, 'Full time'),
        (PART_TIME, 'Part time'),
    )

    name = models.CharField(max_length=120)
    status = models.SmallIntegerField(choices=EMPLOYEE_STATUS_CHOICES, default=PART_TIME)

    def __unicode__(self):
        return self.name

# forms.py
class EmployeeForm(forms.ModelForm):
    class Meta:
        model = Employee

From model and form definition above “status” field will rendered as html dropdown with those 3 option. In some case I have to make it as read only form in my HTML, for instance only display “Part time” choices in the html dropdown. We can override it in form like code below.

def __init__(self, *args, **kwargs):
    super(EmployeeForm, self).__init__(*args, **kwargs)
    # 2 is choices index in model definition above.
    self.fields['status'].choices = [EMPLOYEE_STATUS_CHOICES[2]]

For another case, we have to filter by the value in database, for instance.

$ Employee.objects.create(name="John Doe", status=Employee.INTERNSHIP)

In our views.

# Supposed to be get by `id` or `uuid`
instance = Employee.objects.get(name="John Doe")
form = EmployeeForm(request.POST or None, instance=instance)

We have to set the dropdown following the data in database without display the other choices.

def __init__(self, *args, **kwargs):
    super(EmployeeForm, self).__init__(*args, **kwargs)
    
    if self.instance is None:
        self.fields['status'].choices = [EMPLOYEE_STATUS_CHOICES[2]]
    else:
        status = self.instance.status
        self.fields['status'].choices = [(status, dict(EMPLOYEE_STATUS_CHOICES).get(status))]
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s