什么是ModelForm
顾名思义,ModelForm就是数据模型和表单的结合体。单纯的Form表单只是对数据进行验证、在模板生成HTML。但这个ModelForm也包含了以上Form的功能,这是一个基于数据模型的一个组件,结合数据库使用的。
例一、利用ModelForm添加数据
有以下数据库
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的创建
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': '必须要选部门'}, }
表单中的渲染
{# 循环ModelForm,可获取每个field,相当于form.username、form.ip#} {% for field in form %}{{ field.label }}:{{ field }}{{ field.errors.0 }}
{% endfor %}
View视图函数
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编辑数据
模板
{# 循环ModelForm,可获取每个field,相当于form.username、form.ip#} {% for field in form %}{{ field.label }}:{{ field }}{{ field.errors.0 }}
{% endfor %}
视图函数
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})
要点总结
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模块给个别名,因为这和参数名重复
示例如下:
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类上面定义,如下:
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'}) }
但如果定义的字段名与数据模型重复,会把数据模型的覆盖