# 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]
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] else: status = self.instance.status self.fields['status'].choices = [(status, dict(EMPLOYEE_STATUS_CHOICES).get(status))]