Django之ModelForm
什么是ModelForm
顾名思义,ModelForm就是数据模型和表单的结合体。单纯的Form表单只是对数据进行验证、在模板生成HTML。但这个ModelForm也包含了以上Form的功能,这是一个基于数据模型的一个组件,结合数据库使用的。
例一、利用ModelForm添加数据
有以下数据库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | from django.db import models # Create your models here. class UserInfo(models.Model): username = models.CharField(max_length = 32 ) password = models.CharField(max_length = 32 ) def __str__( self ): return self .username class Host(models.Model): hostname = models.CharField(max_length = 32 , verbose_name = '主机名' ) # verbose_name用于在模板中生成label标签 ip = models.GenericIPAddressField(protocol = 'ipv4' ) port = models.IntegerField() user = models.ForeignKey(to = 'UserInfo' , on_delete = models.CASCADE, default = 1 ) dp = models.ManyToManyField(to = 'Department' ) class Department(models.Model): title = models.CharField(max_length = 32 ) def __str__( self ): return self .title |
ModelForm的创建
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | from django.forms import widgets from app01 import models # 创建一个ModelForm类 class HostModelForm(ModelForm): class Meta: model = models.Host # 定义了引用的数据模型 fields = '__all__' # 定义引用数据模型的哪些字段,也可以为列表,如['username','ip'] # 定义标签名称,也可在数据模型中使用参数verbose_name定义 labels = { 'dp' : '部门' , 'ip' : 'IP' , 'port' : '端口' , 'user' : '用户名' } error_messages = { # 定义错误信息 'hostname' : { 'required' : '用户名不能为空' }, 'ip' : { 'required' : 'ip不能为空' }, 'port' : { 'required' : '端口不能为空' }, 'dp' : { 'required' : '必须要选部门' }, } |
表单中的渲染
1 2 3 4 | { # 循环ModelForm,可获取每个field,相当于form.username、form.ip#} { % for field in form % } <p>{{ field.label }}:{{ field }}{{ field.errors. 0 }}< / p> { % endfor % } |
View视图函数
1 2 3 4 5 6 7 8 9 | def add_host(request): if request.method = = 'GET' : form = forms.HostModelForm() # 用于渲染网页 else : form = forms.HostModelForm(data = request.POST) # 校验数据 if form.is_valid(): form.save() # 保存到数据库 return redirect( '/host/' ) return render(request, 'add_host.html' , { 'form' : form}) |
利用ModelForm编辑数据
模板
1 2 3 4 | { # 循环ModelForm,可获取每个field,相当于form.username、form.ip#} { % for field in form % } <p>{{ field.label }}:{{ field }}{{ field.errors. 0 }}< / p> { % endfor % } |
视图函数
1 2 3 4 5 6 7 8 9 10 | def edit_host(request, nid): host_obj = models.Host.objects. filter ( id = nid).first() if request.method = = 'GET' : form = forms.HostModelForm(instance = host_obj) # 把对象传给ModelForm,以方便于网页渲染 else : form = forms.HostModelForm(data = request.POST, instance = host_obj) # 对instance实例用data更新数据 if form.is_valid(): form.save() return redirect( '/host/' ) return render(request, 'edit_host.html' , { 'form' : form}) |
要点总结
1 2 3 4 5 6 | form = forms.HostModelForm() # 用于渲染空的模板 form = forms.HostModelForm(instance = obj) # 用于渲染一个带有obj数据的模板 form = forms.HostModelForm(data = request.POST) # 准备校验的数据 form = forms.HostModelForm(data = request.POSt, instance = obj) # 对对象obj更新数据 form.save() # 保存数据 form.is_valid() # 校验数据 |
内容补充
插件
这个插件的使用和Form差不多,但注意需要首先给widgets模块给个别名,因为这和参数名重复 示例如下:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | from django.forms import fields from django.forms import Form, ModelForm from django.forms import widgets as mfwidgets # 起一个别命 from app01 import models class HostModelForm(ModelForm): class Meta: model = models.Host # 定义了引用的数据模型 fields = '__all__' # 定义引用数据模型的哪些字段,也可以为列表,如['username','ip'] # 定义标签名称,也可在数据模型中使用参数verbose_name定义 labels = { 'dp' : '部门' , 'ip' : 'IP' , 'port' : '端口' , 'user' : '用户名' } error_messages = { # 定义错误类型 'hostname' : { 'required' : '用户名不能为空' }, 'ip' : { 'required' : 'ip不能为空' }, 'port' : { 'required' : '端口不能为空' }, 'dp' : { 'required' : '必须要选部门' }, } widgets = { # 和form使用方法类似,这里演示了对hostname字段html的生成。 'hostname' : mfwidgets.Textarea(attrs = { 'class' : 'c1' }) } |
钩子函数
和Form一样的添加定制form字段
ModelForm是依赖于数据模型,而现在需要使用的是数据模型以外的字段,可在class Meta类上面定义,如下:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | class HostModelForm(ModelForm): test = fields.CharField() # 新增字段 class Meta: model = models.Host # 定义了引用的数据模型 fields = '__all__' # 定义引用数据模型的哪些字段,也可以为列表,如['username','ip'] # 定义标签名称,也可在数据模型中使用参数verbose_name定义 labels = { 'dp' : '部门' , 'ip' : 'IP' , 'port' : '端口' , 'user' : '用户名' } error_messages = { # 定义错误类型 'hostname' : { 'required' : '用户名不能为空' }, 'ip' : { 'required' : 'ip不能为空' }, 'port' : { 'required' : '端口不能为空' }, 'dp' : { 'required' : '必须要选部门' }, } widgets = { 'hostname' : mfwidgets.Textarea(attrs = { 'class' : 'c1' }) } |
但如果定义的字段名与数据模型重复,会把数据模型的覆盖
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」