Django 中的 forms.ModelForm
—— 它是 Django 表单系统和 ORM 的一个“桥梁”,能帮助你快速基于 数据库模型(Model) 自动生成表单,极大减少重复代码。
1. 什么是 ModelForm
- 普通 Form (
forms.Form
):完全手写字段,和数据库模型没有直接关系。 - ModelForm (
forms.ModelForm
):根据 Django ORM 的 Model 自动生成表单字段,避免重复定义字段。
换句话说,ModelForm
= Form + Model 映射。
你只需要指定关联的模型 model
,Django 会自动:
- 根据模型字段生成对应的表单字段;
- 自动处理数据校验(包括数据库字段约束,如
max_length
、unique
); - 提供
save()
方法,可以直接保存到数据库。
2. 基本用法
模型定义
# models.py
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=50)
published_date = models.DateField()
price = models.DecimalField(max_digits=6, decimal_places=2)
def __str__(self):
return self.title
ModelForm 定义
# forms.py
from django import forms
from .models import Book
class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = '__all__' # 或 ['title', 'author']
视图中使用
# views.py
from django.shortcuts import render, redirect
from .forms import BookForm
def create_book(request):
if request.method == "POST":
form = BookForm(request.POST)
if form.is_valid(): # 自动根据模型字段校验
form.save() # 直接保存到数据库
return redirect('book_list')
else:
form = BookForm()
return render(request, 'book_form.html', {'form': form})
模板中渲染
<form method="post">
{% csrf_token %}
{{ form.as_p }} <!-- 自动渲染为 <p> 包裹的表单控件 -->
<button type="submit">保存</button>
</form>
3. ModelForm
的关键点
3.1 Meta
类配置
ModelForm
必须包含一个 Meta
内部类,用来定义表单和模型的关系。
常用属性:
- model:指定关联的模型
- fields:指定要包含的字段(推荐用列表,不要总用
__all__
) - exclude:排除某些字段
- widgets:指定表单控件样式(比如 HTML input)
- labels:自定义字段的标签
- help_texts:字段提示文字
- error_messages:自定义错误提示
示例:
class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = ['title', 'author', 'price'] # 只要部分字段
labels = {
'title': '书名',
'author': '作者',
}
help_texts = {
'price': '请输入价格(单位:元)',
}
error_messages = {
'title': {
'max_length': '书名太长了!',
},
}
widgets = {
'published_date': forms.SelectDateWidget(years=range(2000, 2030)),
}
4. 表单数据的保存
4.1 新增
form = BookForm(request.POST)
if form.is_valid():
book = form.save() # 直接保存到数据库
4.2 不立即保存
有时候需要在保存前修改对象,可以用 commit=False
:
book = form.save(commit=False)
book.price = book.price * 0.9 # 打折
book.save()
4.3 更新已有对象
book = Book.objects.get(pk=1)
form = BookForm(request.POST, instance=book) # 绑定已有对象
if form.is_valid():
form.save() # 会执行 update 而不是 insert
5. 表单校验
5.1 自动校验
- 来自模型字段的限制(
max_length
、unique
、blank
等) - 自动映射到表单校验规则
5.2 自定义校验
可以通过重写 clean_<field>()
或 clean()
:
方法名中的<field>
必须和表单字段名一致;
class BookForm(forms.ModelForm):
class Meta:
model = Book
fields = '__all__'
def clean_price(self):
price = self.cleaned_data['price']
if price <= 0:
raise forms.ValidationError("价格必须大于0!")
return price
def clean(self):
cleaned_data = super().clean()
title = cleaned_data.get('title')
author = cleaned_data.get('author')
if title and author and "Django" not in title and author == "某某":
raise forms.ValidationError("某某只能写 Django 相关的书!")
return cleaned_data
调用顺序:
- 表单调用了
is_valid()
,从而触发了full_clean() → clean_fields() → clean_<field>()
。
6. ModelForm
的高级用法
6.1 内联表单(Inline Formset)
Django 提供了 inlineformset_factory
,可以在一个表单中编辑主表和子表。
常用于:一个 Author
对应多个 Book
的场景。
from django.forms import inlineformset_factory
BookFormSet = inlineformset_factory(Author, Book, fields=['title', 'price'])
6.2 ModelForm
与 modelform_factory
如果表单逻辑简单,可以用 modelform_factory
快速生成:
from django.forms import modelform_factory
BookForm = modelform_factory(Book, fields=['title', 'author'])
7. Form
vs ModelForm
对比
特点 | Form | ModelForm |
---|---|---|
字段定义 | 手动写每个字段 | 自动从 Model 生成 |
数据校验 | 需手动写 | 自动结合 Model 的字段规则 |
保存到数据库 | 需手动处理模型对象保存 | 直接用 save() |
使用场景 | 与数据库无关的表单 | 与模型强关联的 CRUD 表单 |
8. 使用场景总结
✅ 适合:
- 表单与数据库模型字段高度一致的场景(如后台管理系统、标准 CRUD 表单)
- 希望快速生成表单,减少重复代码
⚠️ 不适合:
- 表单和模型差别很大(例如前端提交的数据字段和数据库存储结构完全不一样)
- 需要复杂的自定义逻辑时,建议继承
forms.Form