ModelForms
A Django ModelForm is a form class built automatically from a model — it inspects the model's fields, generates matching form fields and validation, and can save submitted data straight back to the database with a single save() call.
Learn ModelForms in our free Django course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Django course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
In this lesson you'll define a ModelForm with its inner Meta class, use it in a view to create records, set extra fields before saving, and reuse the same form to edit existing objects.
A ModelForm is a class that subclasses forms.ModelForm and contains an inner class called Meta . The Meta class tells Django two things: which model the form is built from, and which fields of that model to include.
Say you have a Post model. The ModelForm below reads its title and body columns and generates the matching form fields, complete with the validation Django infers from each model field:
You control the included fields three ways inside Meta :
The big payoff of a ModelForm is form.save() . When the submitted data is valid, one call writes a new row to the database. A typical create view checks request.method , validates with is_valid() , then saves:
Sometimes the model needs a value the user shouldn't supply — like the author , which should be the logged-in user. Use save(commit=False) to build the object without hitting the database, set the extra field, then call save() yourself:
To edit an existing record, pass it as the instance argument. On a GET request the form renders pre-filled with the object's current values; on a POST you pass both the data and the instance so save() updates that row instead of creating a new one:
You can also customise how fields render right inside Meta using widgets and labels . For example, make the body a larger textarea and give the title a friendlier label:
Fill in the blanks so the helper reports the correct model and fields for a ModelForm built from the Post model that shows only title and body .
❌ ValueError: ModelForm has no model class specified
You forgot the inner Meta class, or it doesn't set model .
✅ Fix: add class Meta: with model = Post inside your form.
No fields were listed, so Django generated a form with nothing on it.
You called form.save(commit=False) and then forgot the final .save() .
✅ Fix: after setting your extra fields, call post.save() on the returned object.
Model the full lifecycle: create a post with save(commit=False) to attach an author, then edit it through the same form using an instance.
Lesson 11 complete — you can build forms straight from your models!
You now know how to define a ModelForm with its inner Meta class, choose its fields, save new records with save(), set extra fields with save(commit=False), and edit existing objects by passing an instance.
🚀 Up next: Class-Based Views — let Django's generic views handle create, edit, and list pages for you.
Practice quiz
What is a ModelForm built from?
- A URL pattern
- A model
- A template
- A migration
Answer: A model. A ModelForm is generated automatically from a model.
Which base class does a ModelForm subclass?
- forms.Form
- forms.ModelForm
- models.Model
- forms.BaseForm
Answer: forms.ModelForm. A ModelForm subclasses forms.ModelForm.
Where do you specify the model and fields for a ModelForm?
- In the view
- In a settings file
- In the inner Meta class
- In urls.py
Answer: In the inner Meta class. The inner Meta class sets model and fields.
Which Meta option includes every model field?
- fields = '__all__'
- fields = 'every'
- include = 'all'
Answer: fields = '__all__'. fields = '__all__' includes every field on the model.
Why is an explicit fields list recommended over '__all__'?
- It is faster
- It prevents new model fields from silently appearing on the form
- It is required
- It enables validation
Answer: It prevents new model fields from silently appearing on the form. An explicit list keeps newly added fields off the form automatically.
What does form.save() do when data is valid?
- Renders the template
- Validates only
- Deletes the row
- Writes a row to the database
Answer: Writes a row to the database. form.save() writes the row when the form is valid.
What does form.save(commit=False) return?
- A boolean
- The form HTML
- An unsaved model instance
- A QuerySet
Answer: An unsaved model instance. It returns an unsaved object so you can set extra fields first.
After save(commit=False) and setting extra fields, what must you do?
- Nothing, it auto-saves
- Call .save() on the returned object
- Call form.clean()
- Redirect immediately
Answer: Call .save() on the returned object. You must call .save() on the object to persist it.
How do you edit an existing record with a ModelForm?
- Pass it as the instance argument
- Use a new form class
- Call update()
- Set fields = 'edit'
Answer: Pass it as the instance argument. Pass the object via instance so save() updates that row.
Which Meta option customises how a field renders, like a larger textarea?
- labels
- help_texts
- widgets
- fields
Answer: widgets. widgets lets you set, e.g., forms.Textarea for a field.