I still find myself comparing Rails and Django — forms are one thing they handle quite differently, and I really enjoy the way Django does them. Class-based forms are such an easy way to manipulate the information that goes into and out of your forms, and provides a great way to put some of the logic in the form itself, providing a separation from the form and the controller logic.
This only covers user-facing Model forms, not Django Admin forms, or non-model forms. However, once you’ve built model forms, you’ll find you can use the same concepts to build other types of forms.
As always, here are the docs.
Creating the Form
A ModelForm is used for creating or editing an instance of an object in the database.
Let’s say we have the following model:
from django.conf import settings
from django.db import modelsclass Meal(models.Model):
organizer = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='organizer')
time = models.DateTimeField(null=True, blank=True)
location = models.CharField(max_length=100)
required = models.NullBooleanField(default=None)
Here’s an example that shows just a couple things you can do to customize its behavior. We’ll talk through each of them.
from django import forms
from django.forms import fields, CheckboxInputclass MealForm(forms.ModelForm) class Meta:
model = Meal
fields = ('time', 'location') def __init__(self, *args, **kwargs):
self.organizer = kwargs.pop('organizer')
super(MealForm, self).__init__(*args, **kwargs)
if not self.instance:
self.fields['location'].initial = self.organizer.default_location
self.fields['required'].widget = CheckboxInput(required=False) def clean_time(self):
time = self.cleaned_data['time']
# do stuff with the time to put it in UTC based on the user's default timezone and data passed into the form. def save(self, *args, **kwargs):
self.instance.organizer = self.organizer
meal = super(MealForm, self).save(*args, **kwargs)
When creating a model form, you have to tell it which model it’s working with in the
Meta class, and…