8.2 使用表单系统实现表单: ModelForm
2025-02-17
- 表单系统的核心:Form对象,它将表单中的字段封装成一系列Field和验证规则,以此来自动地生成HTML表单标签
8.2.1 使用Form对象定义表单
Django的建议将它们定义在应用下的:forms.py文件中
# forms.py """ Form 表单对象 """ from django import forms class TopicSearchForm(forms.Form): title = forms.CharField(label='Topic title')Django规定,所有的Form对象都必须继承自django.forms.Form,所以这里的TopicSearchForm符合条件。
定义了一个title属性,它是forms.CharField类型的Field,根据名称可以猜测此处将title指定为字符类型。
label标签显式地指定了这个字段的名称,且Field有一个默认属性required为True,代表这个字段是必填的。
Forms对象的特性
- 实现对所有字段的验证
- 根据字段定义生成HTML
- 表单实例可以自动生成HTML表单元素,且默认输出使用HTML表格,但是并不提供
<table>起始和结束标签。 - 同时,也可以使用实例的as_ul方法获取列表形式的表单或使用as_p方法获取段落形式的表单
- 表单实例可以自动生成HTML表单元素,且默认输出使用HTML表格,但是并不提供
8.2.2 基于Model定制的表单
- Django表单系统考虑到了这个问题,提供了ModelForm,可以基于Model的定义自动生成表单,很大程度上简化了Model翻译成表单的过程
- 不会翻译所有的字段,editable=False的模型字段都不会出现在ModelForm中,如自增主键、自动添加的时间字段等
- ModelForm的使用方法与Form类似,同样可以使用
is_valid方法校验字段值的合法性和通过cleaned_data属性获取清理后的字段值 - 另外,ModelForm也会校验模型字段中设置的限制条件。如Topic中的title字段存在唯一性限制,那么,当表单对象执行is_valid方法时,不仅会校验title的字面值,同时还会查询数据库确认不存在重复的记录
简单的ModelForm
定义一个TopicModelForm表单类
# forms.py ## 基于Model复制表单 class TopicModelForm(forms.ModelForm): class Meta: # 使用Meta设置必要的元信息 model = Topic # 指定需要生成表单的模型(model) exclude = ('is_online', 'user') # 排除不需要在表单中显示的字段应用到html视图中
<!-- topic_model_form.html --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Topic Model Form</title> </head> <body> <form action="" method="POST"> <table> {{ form }} </table> {% csrf_token %} <input type="submit" value="提交"> </form> </body> </html>action 没有设定URL的意思是:将表单提交到与当前页面相同的URL
视图函数编写
def topic_model_form(request): if request.method == 'POST': topic = TopicModelForm(request.POST) if topic.is_valid(): topic = Topic.objects.create(title=topic.cleaned_data['title'], content=topic.cleaned_data['content'], user=request.user) return topic_detail_view(request, topic.id) else: return render(request, 'post/topic_model_form.html', context={'form': topic}) else: return render(request, 'post/topic_model_form.html', context={'form': TopicModelForm()})
常用的Meta选项
fields:列表或元组类型,与exclude相反,指定当前表单应该包含那些字段
- 要所有Model字段都包含在表单中,可以设定为:
fields='__all__'
ModelForm的定义必须要包含fields或exclude选项
- 要所有Model字段都包含在表单中,可以设定为:
labels:字典类型,用于定义表单字段的名称(输入框左边显示的名称)
表单字段的名称首先会使用Model字段设置的
verbose_name,没有设置则直接使用字段名当没有设置verbose_name是,就可以使用labels选项指定字段名
labels = { 'title':'标题', 'content':'内容' }
help_texts:字典类型,用于给表单字段添加帮助信息(输入框下方显示的内容)来自Model字段的help_texts定义。help_texts与labels选项类似
widgets:字典类型,用于定义表单字段选用的控件。ModelForm会根据Model字段的类型映射表单Field类,因此会应用Field类中默认定义的widgets。
field_classes:字典类型,指定表单字段使用的Field类型,默认情况下,对于title字段,ModelForm会将它映射为fields.CharField类型。可以根据需要改变这种默认行为,例如,将title设置为form s.EmailField类型
field_classes = { 'title': forms.EmailField }