Django ModelForm 实战:从基础用法到数据验证与编辑
本文详解 Django 中 ModelForm 组件的核心用法。通过定义继承自 ModelForm 的类及 Meta 内部类,可自动将数据库模型映射为前端表单。内容涵盖字段显示、自定义 Widget 样式、错误信息处理,以及利用 instance 参数实现数据的自动回显与更新保存,旨在提供比手动编写表单更优雅高效的后端解决方案。
这是一个功能强大的组件,从名称即可推断其作用:将 Model(模型)与 Form(表单)结合。没错,正如你预期的那样,它旨在简化这两者的交互。
首先通过一个简单示例展示其基本用法:
假设数据库中有一张学生表,包含姓名、年龄、爱好、邮箱、电话、住址、注册时间等多个字段。现在需要开发一个创建学生的页面,后端应如何处理?
常规做法是前端逐一列出这些字段供用户填写,后端逐一接收输入,创建新的学生对象并保存。
然而,核心难点在于合法性验证。我们需要在前端判断用户输入是否符合规范,例如姓名长度限制、电话号码位数、邮箱格式等。
虽然可以手动编写各种限制和判断逻辑,但这显然繁琐且低效。
这里提供一种更优雅(在 Python 开发中应养成使用“优雅”一词的习惯)的方法:ModelForm。
先演示基本用法,随后再添加验证条件:
首先导入 ModelForm 模块。
from django.forms import ModelForm
在视图函数中定义一个类(例如 StudentList),该类需继承 ModelForm。在此类内部定义一个名为 Meta 的内部类(注意首字母大写,这是固定写法)。
在 Meta 内部类中,可以配置以下属性(部分示例):
class StudentList(ModelForm):
class Meta:
model = models.Student #对应的Model中的类
fields = "__all__" #字段,如果是__all__,就是表示列出所有的字段
exclude = None #排除的字段
labels = None #提示信息
help_texts = None #帮助提示信息
widgets = None #自定义插件
error_messages = None #自定义错误信息
#error_messages用法:
error_messages = {
'name':{'required':"用户名不能为空",},
'age':{'required':"年龄不能为空",},
}
#widgets用法,比如把输入用户名的input框给为Textarea
#首先得导入模块
from django.forms import widgets as wid #因为重名,所以起个别名
widgets = {
"name":wid.Textarea(attrs={"class":"c1"}) #还可以自定义属性
}
#labels,自定义在前端显示的名字
labels= {
"name":"用户名"
}
接着,在 URL 对应的视图函数中实例化该类,并将该对象传递给前端模板。
def student(request):
if request.method == 'GET':
student_list = StudentList()
return render(request,'student.html',{'student_list':student_list})
前端只需使用 {{ student_list.as_p }} 即可渲染所有字段。虽然可以使用 as_p 直接显示,但也可以通过 for 循环遍历 student_list,获取各个 input 框。为了获得更好的页面效果,我们通常不使用 as_p,而是手动构建这些 input 框。
首先对 student_list 进行 for 循环,获取 student 对象,直接在前端打印该对象即可得到 input 框。通过 student.label 可以获取数据库中每个字段的 verbose_name(如果未设置,则默认显示字段名)。
此外,还可以通过 student.errors.0 获取具体的错误信息。
利用上述信息,我们可以结合 Bootstrap 框架自定义所需的页面样式。
例如:
<body>
<div class="container" >
<h1>student</h1>
<form method="POST" novalidate>
{% csrf_token %}
{# {{ student_list.as_p }}#}
{% for student in student_list %}
<div class="form-group col-md-6">
{# 拿到数据字段的verbose_name,没有就默认显示字段名 #}
<label class="col-md-3 control-label">{{ student.label }}</label>
<div class="col-md-9" style="position: relative;">{{ student }}</div>
</div>
{% endfor %}
<div class="col-md-2 col-md-offset-10">
<input type="submit" value="提交" class="btn-primary">
</div>
</form>
</div>
</body>
目前还缺少 input 框的 form-control 样式,可以考虑在后台的 widget 配置中添加。
具体配置如下:
from django.forms import widgets as wid #因为重名,所以起个别名
widgets = {
"name":wid.TextInput(attrs={'class':'form-control'}),
"age":wid.NumberInput(attrs={'class':'form-control'}),
"email":wid.EmailInput(attrs={'class':'form-control'})
}
当然,也可以在 JavaScript 中查找所有 input 框并动态添加该样式,这也是可行的替代方案。
在保存数据时,无需逐个提取数据,直接调用 save() 方法即可。
def student(request):
if request.method == 'GET':
student_list = StudentList()
return render(request,'student.html',{'student_list':student_list})
else:
student_list = StudentList(request.POST)
if student_list.is_valid():
student_list.save()
return redirect(request,'student_list.html',{'student_list':student_list})
接下来介绍编辑数据的场景:
如果不使用 ModelForm,编辑时需手动显示原有数据并逐个取值。而使用 ModelForm 时,只需在实例化时添加 instance=obj(obj 为待修改的数据库记录对象)即可实现同样的回显效果。
保存数据时需特别注意:必须传入该对象(instance=obj),否则系统无法确定更新哪一条数据。
相关代码示例如下:
from django.shortcuts import render,HttpResponse,redirect
from django.forms import ModelForm
# Create your views here.
from app01 import models
def test(request):
# model_form = models.Student
model_form = models.Student.objects.all()
return render(request,'test.html',{'model_form':model_form})
class StudentList(ModelForm):
class Meta:
model = models.Student #对应的Model中的类
fields = "__all__" #字段,如果是__all__,就是表示列出所有的字段
exclude = None #排除的字段
labels = None #提示信息
help_texts = None #帮助提示信息
widgets = None #自定义插件
error_messages = None #自定义错误信息
#error_messages用法:
error_messages = {
'name':{'required':"用户名不能为空",},
'age':{'required':"年龄不能为空",},
}
#widgets用法,比如把输入用户名的input框给为Textarea
#首先得导入模块
from django.forms import widgets as wid #因为重名,所以起个别名
widgets = {
"name":wid.Textarea
}
#labels,自定义在前端显示的名字
labels= {
"name":"用户名"
}
def student(request):
if request.method == 'GET':
student_list = StudentList()
return render(request,'student.html',{'student_list':student_list})
else:
student_list = StudentList(request.POST)
if student_list.is_valid():
student_list.save()
return render(request,'student.html',{'student_list':student_list})
def student_edit(request,pk):
obj = models.Student.objects.filter(pk=pk).first()
if not obj:
return redirect('test')
if request.method == "GET":
student_list = StudentList(instance=obj)
return render(request,'student_edit.html',{'student_list':student_list})
else:
student_list = StudentList(request.POST,instance=obj)
if student_list.is_valid():
student_list.save()
return render(request,'student_edit.html',{'student_list':student_list})
总结
以上为 Django 中 ModelForm 组件的详细用法说明,希望对你有所帮助。感兴趣的朋友可继续查阅本站其他 Python 相关教程,如有疏漏欢迎留言指正。感谢支持!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













