一. 创建一个ModelForm
1.1 使用之前需要导入对应app中的models和Django提交的ModelForm类
from django.forms import ModelForm
from app01.models import Host
from django.forms import widgets #插件,接下来会用到
from django.core.exceptions import ValidationError
1.2 创建一个类,并继承ModelForm
class HostModelForm(ModelForm): #新建1个类,继承ModelForm
class Meta: #在内部定义一个Meta类,注意这个类名是固定不变的
model = Host #对应models.py中哪个类(哪个表)
fields = '__all__' #表示使用models.Host类中所有字段
# fields = ('hostname','ip','port','dep') #也可以这样选择指定字段
ModelForm常用的class Meta配置
class Meta:
model = models.UserInfo #结尾不用加逗号
fields = '__all__'
# fields = ['username','email']
# exclude = ['username'] # 除了 XX字段,其他都使用
labels = { # label 名称
'username': '用户名',
'email': '邮箱',
}
help_texts = { # 帮助信息
'username': '...'
}
widgets = {
'username': Fwidgets.Textarea(attrs={'class': 'c1'})
}
error_messages = { # 自定义错误
'__all__':{
},
'email': {
'required': '邮箱不能为空',
'invalid': '邮箱格式错误..',
}
}
field_classes = { #字段类型,可以强制修改成其他类型
# 'email': Ffields.URLField
}
# localized_fields=('ctime',)
二. ModelForm生成Html和数据验证
2.1 生成空表单
forms = HostModelForm() # 生成空的表单
2.2 在表单中显示初始数据
hostobj =models.Host.objects.get(id=1)
forms = HostModelForm(instance = hostobj) # instance 对应模型实例
2.3 验证表单数据并保存
forms = HostModelForm(request.POST)
if forms.is_valid(): # 验证成功则保存modelsform
forms.save() # 这一步会直接将数据保存至数据库
注意:此时,forms.save()不仅保存当前对象实例,还保存实例对应跨表关系(外键、多对多等)
三. 前端页面展示form表
在模版中展示指定字段
<form method="post" novalidate>
{% csrf_token %}
<p>{{ forms.hostname.label }}: {{ forms.hostname }}{{ forms.hostname.errors.0 }}</p>
<p>{{ forms.ip.label }}: {{ forms.ip }}{{ forms.ip.errors.0 }}</p>
<p>{{ forms.port.label }}: {{ forms.port }}{{ forms.port.errors.0 }}</p>
<input type="submit" value="提交">
</form>
如果嫌上面这种方法麻烦,还可以在模版中循环forms实例,以列出每个字段
<form method="post" novalidate>
{% csrf_token %}
{% for form in forms %}
<p>{{ form.label }}: {{ form }}{{ form.errors.0 }}</p>
{% endfor %}
<input type="submit" value="提交">
</form>
四. 示例
4.1 在app中创建一个forms.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# Author : Cai Guangyin
from django.forms import ModelForm
from app01.models import Host
from django.forms import widgets
from django.core.exceptions import ValidationError
class HostModelForm(ModelForm): #新建1个类,继承ModelForm
class Meta:
model = Host #对应models.py中哪个类(哪个表)
fields = '__all__' #表示使用models.Host类中所有字段
# fields = ('hostname','ip','port','dep') #也可以这样选择指定字段
error_messages = { #自定义错误提示信息
'hostname':{
'required':'用户名不能为空'
},
'ip':{
'required':'IP不能为空',
'invalid':'IP地址格式错误'
},
'port':{
'required':'端口不能为空'
},
'dep': {
'required': '部门不能为空'
},
'userinfo': {
'required': '所属用户不能为空'
},
}
labels = { #自定义label标签显示的内容
'hostname':'主机名',
'ip':'IP',
'port':'端口',
'dep':'部门',
'userinfo':'所属用户'
}
widgets = { # 自定义插件,注意必须加s,因为是复数,写widget不起作用
'hostname': widgets.TextInput(attrs={'class':'form-control'}),
'ip': widgets.TextInput(attrs={'class':'form-control'}),
'port': widgets.TextInput(attrs={'class':'form-control'}),
'dep': widgets.Select(attrs={'class':'form-control'}),
'userinfo': widgets.SelectMultiple(attrs={'class':'form-control'}),
}
def clean_port(self): #也可以自定义钩子函数对字段进行验证
value = self.cleaned_data['port']
if int(value) > 65535:
raise ValidationError('端口号不能大于65535')
return value
4.2 views.py
from django.shortcuts import render
from .models import *
from .forms import HostModelForm
# Create your views here.
def index(request):
forms = HostModelForm() #创建空表单
if request.method == 'POST':
forms = HostModelForm(request.POST) #提交数据
if forms.is_valid(): #验证数据
forms.save()
return render(request,'index.html',locals())
def edit_host(request):
host_obj = Host.objects.filter(pk=1).first()
forms = HostModelForm(instance=host_obj) #编辑时显示默认数据
if request.method == 'POST':
# host_obj = Host.objects.filter(pk=1).first()
# forms = HostModelForm(request.POST) #向modelform中传递数据
forms = HostModelForm(data=request.POST,instance=host_obj) #编辑保存时,需要将data和instance都传入
if forms.is_valid():
forms.save()
return render(request,'edithost.html',locals())
注意:在修改表单(表单中有初始值),提交验证时,需要传入data和instance两个参数,如:
forms = HostModelForm(data=request.POST,instance=host_obj)
4.3 模版文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="post" novalidate>
{% csrf_token %}
{% for form in forms %}
<p>{{ form.label }}: {{ form }}{{ form.errors.0 }}</p>
{% endfor %}
<input type="submit" value="提交">
</form>
</body>
</html>