Django ModelForm表单验证
ModelForm
在使用Model和Form时,都需要对字段进行定义并指定类型,通过ModelForm则可以省去From中字段的定义
应用场景:定制model admin 的时候可以使用。适用于小业务架构。
ModelForm a. class Meta: model, # 对应Model的 fields=None, # 字段 exclude=None, # 排除字段 labels=None, # 提示信息 help_texts=None, # 帮助提示信息 widgets=None, # 自定义插件 error_messages=None, # 自定义错误信息(整体错误信息from django.core.exceptions import NON_FIELD_ERRORS) field_classes=None # 自定义字段类 (也可以自定义字段) localized_fields=('birth_date',) # 本地化,如:根据不同时区显示数据 如: 数据库中 2016-12-27 04:10:57 setting中的配置 TIME_ZONE = 'Asia/Shanghai' USE_TZ = True 则显示: 2016-12-27 12:10:57 b. 验证执行过程 is_valid -> full_clean -> 钩子 -> 整体错误 c. 字典字段验证 def clean_字段名(self): # 可以抛出异常 # from django.core.exceptions import ValidationError return "新值" d. 用于验证 model_form_obj = XXOOModelForm() model_form_obj.is_valid() model_form_obj.errors.as_json() model_form_obj.clean() model_form_obj.cleaned_data e. 用于创建 model_form_obj = XXOOModelForm(request.POST) #### 页面显示,并提交 ##### # 默认保存多对多 obj = form.save(commit=True) # 不做任何操作,内部定义 save_m2m(用于保存多对多) obj = form.save(commit=False) obj.save() # 保存单表信息 obj.save_m2m() # 保存关联多对多信息 f. 用于更新和初始化 obj = model.tb.objects.get(id=1) model_form_obj = XXOOModelForm(request.POST,instance=obj) ... PS: 单纯初始化 model_form_obj = XXOOModelForm(initial={...})
views.py
class UserInfoModelForm(forms.ModelForm): class Meta(object): model = models.UserInfo fields = '__all__' # 请求处理 class ModelFormTest(View): def get(self, request): # ModelForm 创建对象 verify_obj = UserInfoModelForm() return render(request, 'modelForm.html', {'verify_obj': verify_obj})
models.py
class UserType(models.Model): caption = models.CharField(max_length=32) class UserInfo(models.Model): username = models.CharField(verbose_name='用户名', max_length=32) email = models.EmailField() user_type = models.ForeignKey(to=UserType, to_field='id', on_delete=models.SET_NULL,null=True)
注:verbose_name 为django admin管理数据 的时候显示 的字段。在模板中渲染时,调用modelForm对象实例也可以显示对应的中文
{{ verify_obj.as_p }}
{{ verify_obj.as_ul }}
{{ verify_obj.as_table }}
modelForm.html
<form action="/modelformtest/" method="post"> {% csrf_token %} {{ verify_obj.as_p }} <input type="submit" value="提交"> </form>
访问效果
-------------------------------------------------------------------------------------------------------------
只展示指定列 fields =
class UserInfoModelForm(forms.ModelForm): class Meta(object): model = models.UserInfo # fields = '__all__' fields = ['username', ]
排除指定列 :exclude = ['xxx',...]
class UserInfoModelForm(forms.ModelForm): class Meta(object): model = models.UserInfo # fields = '__all__' # fields = ['username', ] exclude = ['username']
labels 效果等于models.py里面定义数据表字段时的 verbose_name='xxx'
为对输入字段自定义提示语
views.py
class UserInfoModelForm(forms.ModelForm): class Meta(object): model = models.UserInfo # 从哪个models 数据表里面获取字段 fields = '__all__' # 展示哪些字段 labels = { # 生成html标签的对应input标签前面的提示 'username': 'lables 用户名', 'email': '邮箱', 'user_type': '用户类型' } class ModelFormTest(View): def get(self, request): # ModelForm 创建对象 verify_obj = UserInfoModelForm() return render(request, 'modelForm.html', {'verify_obj': verify_obj})
modelForm.html
<form action="/modelformtest/" method="post"> {% csrf_token %} {{ verify_obj.as_p }} <input type="submit" value="提交"> </form>
------------------------------------------------------------------------
help_texts=None, # 帮助提示信息
views.py
class UserInfoModelForm(forms.ModelForm): class Meta(object): model = models.UserInfo # 从哪个models 数据表里面获取字段 fields = '__all__' # 展示哪些字段 help_texts = { # 提示信息 'username': '用户名哦', 'email': '邮箱啊' } class ModelFormTest(View): def get(self, request): # ModelForm 创建对象 verify_obj = UserInfoModelForm() return render(request, 'modelForm.html', {'verify_obj': verify_obj})
html
{{ verify_obj.as_p }}
--------------------------------------------------------------------
widgets=None, # 自定义标签类型插件
wiews.py
class UserInfoModelForm(forms.ModelForm): class Meta(object): model = models.UserInfo # 从哪个models 数据表里面获取字段 fields = '__all__' # 展示哪些字段 widgets = { 'username': forms_widgets.Textarea(attrs={'class': 'test-class'}) } class ModelFormTest(View): def get(self, request): # ModelForm 创建对象 verify_obj = UserInfoModelForm() return render(request, 'modelForm.html', {'verify_obj': verify_obj})
html
<form action="/modelformtest/" method="post"> {% csrf_token %} {{ verify_obj.as_p }} <input type="submit" value="提交"> </form>
--------------------------------------------------------------------------------------------
error_messages = {'字段名': {'错误类型': '错误提示', ... }}
class UserInfoModelForm(forms.ModelForm):
class Meta(object):
model = models.UserInfo # 从哪个models 数据表里面获取字段
fields = '__all__' # 展示哪些字段
error_messages = {
'email': {
'required': '必填',
'invalid': '邮箱格式错误'
},
'username': {
'max_length': '太长了',
'min_length': '太短了',
}
}
class ModelFormTest(View):
def get(self, request):
# ModelForm 创建对象
verify_obj = UserInfoModelForm()
return render(request, 'modelForm.html', {'verify_obj': verify_obj})
def post(self, request):
# 获取所有数据
# 每条数据请求的验证
# 成功显示正确信息
# 失败,给出错误提示
# 验证时将request.POST 传递给验证类,实例化验证对象
# verify_obj = MyFm(request.POST)
verify_obj = UserInfoModelForm(request.POST)
verify_result = verify_obj.is_valid() # 验证是否通过,返回True/False
if not verify_result:
return render(request, 'modelForm.html', {'verify_obj': verify_obj})
# 整体错误信息使用 '__all__' 代表所有字段
error_messages = {
'__all__': {
'required': '必填',
'invalid': '格式错误'
},
}
生成html浏览器查看效果
-------------------------------------------
field_classes 更改原有字段生成的html标签类型
views.py
class UserInfoModelForm(forms.ModelForm): class Meta(object): model = models.UserInfo # 从哪个models 数据表里面获取字段 fields = '__all__' # 展示哪些字段 from django.forms import fields as form_fields field_classes = { 'email':form_fields.URLField }
-------------------------------------------------------------------------------------------------
localized_fields=('birth_date',) # 将数据本地化显示,如:根据不同时区显示数据
前提:
需要在settings.py中设置好本地的时区
# setting中的配置 TIME_ZONE = 'Asia/Shanghai' # 时区 USE_TZ = True # 启用本地时区
views.py
localized_fields=('birth_date',) # 本地化,如:根据不同时区显示数据 # 如数据库中存的 2016-12-27 04:10:57 # 则前端显示:2016-12-27 12:10:57
ModelForm 的数据库保存方式
验证有效,直接使用验证实例.save() 保存到数据库
views.py
class ModelFormTest(View): def get(self, request): # ModelForm 创建对象 verify_obj = UserInfoModelForm() return render(request, 'modelForm.html', {'verify_obj': verify_obj}) def post(self, request): # 获取所有数据 # 每条数据请求的验证 # 成功显示正确信息 # 失败,给出错误提示 # 验证时将request.POST 传递给验证类,实例化验证对象 # verify_obj = MyFm(request.POST) verify_obj = UserInfoModelForm(request.POST) if verify_obj.is_valid(): # 默认保存多对多 :第三张表的数据 verify_obj.save() # 不做任何操作,内部定义 save_m2m(用于保存多对多) #verify_obj.save(commit=False) #verify_obj.save() # 保存单张表信息 #verify_obj.save_m2m() # 保存关联多对多 第三张表的信息
models.py
数据表结构UserInfo UserType UserGroup
UserInfo ---> UserType 一对多
UserInfo<----> UserGroup 多对多
class UserType(models.Model): caption = models.CharField(max_length=32) def __str__(self): return self.caption class UserGroup(models.Model): name = models.CharField(max_length=32) class UserInfo(models.Model): username = models.CharField(verbose_name='用户名', max_length=32) email = models.EmailField() user_type = models.ForeignKey(to=UserType, to_field='id', on_delete=models.SET_NULL,null=True) u_in_g = models.ManyToManyField(UserGroup)
-----------------------------------------------------------------------
应用案例:用户列表 查看/编辑用户信息,保存到数据库
models.py
UserInfo 表 user_type字段外键UserType id字段
UserInfo 表u_in_g 字段外键 多对多 UserGroup表id字段
from django.db import models # Create your models here. class UserType(models.Model): caption = models.CharField(max_length=32) def __str__(self): return self.caption class UserGroup(models.Model): name = models.CharField(max_length=32) def __str__(self): return self.name class UserInfo(models.Model): username = models.CharField(verbose_name='用户名', max_length=32) email = models.EmailField() user_type = models.ForeignKey(to=UserType, to_field='id', on_delete=models.SET_NULL,null=True) u_in_g = models.ManyToManyField(UserGroup)
查已保存的数据信息展示给前端
ModelForm 指定instance 数据对象(自定义的数据表 具体的查询结果对象),可以显示给前端
例如:user_html_obj = UserInfoModelForm(instance=user_data)
更新数据库中的信息
例如:
user = models.UserInfo.objects.filter(id=uid).first()
mf_obj = UserInfoModelForm(request.POST, instance=user)
mf_obj.save()
验证post请求的数据有效。更新到指定的查询结果中去,如果不指定instance 则为新增数据操作
views.py
class UserList(View): def get(self, request): users = models.UserInfo.objects.all().select_related('user_type') return render(request, 'modelForm_user_lisst.html' , {'users': users}) class UserEdit(View): def get(self, request, uid): user_data = models.UserInfo.objects.filter(id=uid).first() print('数据查询:', type(user_data)) # 将数据库查询出来的数据对象 user_html_obj = UserInfoModelForm(instance=user_data) return render(request, 'ModelForm_user_edit.html', {'user_html_obj': user_html_obj, 'uid': uid}) pass def post(self, request,uid): user = models.UserInfo.objects.filter(id=uid).first() mf_obj = UserInfoModelForm(request.POST, instance=user) # 更新的数据符合要求,保存到数据库 if mf_obj.is_valid(): mf_obj.save() else: print(mf_obj.errors.as_json) return render(request, 'ModelForm_user_edit.html', {'user_html_obj': mf_obj, 'uid': uid})
modelForm的钩子
验证顺序:is_valid-->full_clean-->clean_fields-->clean_form-->_post_clean
1、在验证数据合法,保存到数据库之前,对验证的数据进行修改
定义 def clean_字段名():函数 对self.cleaned_data中获取到的字段进行修改
class UserInfoModelForm(forms.ModelForm): class Meta(object): #..................... def clean_username(self): old_username = self.cleaned_data.get('username') return old_username + '呵呵'
增加不存储于数据库的字段
应用场景:是否记住登录
views.py
from django.shortcuts import render from django.views import View from django import forms from modelForm_study import models from django.forms import widgets as forms_widgets # Create your views here. class UserInfoModelForm(forms.ModelForm): # 在生成前端标签的时候增加的字段(相比数据库表里面的字段) rember_login = forms.CharField( widget=forms_widgets.CheckboxInput(),
required=False # 是否必填 ) class Meta(object): model = models.UserInfo # 从哪个models 数据表里面获取字段 fields = '__all__' # 展示哪些字段 from django.forms import fields as form_fields # field_classes = { # 改变原有字段类型 # 'email':form_fields.URLField # } error_messages = { '__all__': { 'required': '必填', 'invalid': '格式错误' }, 'email': { 'required': '必填', 'invalid': '邮箱格式错误' }, 'username': { 'max_length': '太长了', 'min_length': '太短了', } } help_texts = { # 提示信息 'username': '用户名哦', 'email': '邮箱啊' } labels = { # 生成html标签的对应input标签前面的提示 'username': 'lables 用户名', 'email': '邮箱', 'user_type': '用户类型', 'u_in_g': '所在组', } # widgets = { # 'username': forms_widgets.Textarea(attrs={'class': 'test-class'}) # } # fields = ['username', ] # exclude = ['username'] # def clean_username(self): # old_username = self.cleaned_data.get('username') # return old_username + '呵呵' # 请求处理 class UserList(View): def get(self, request): users = models.UserInfo.objects.all().select_related('user_type') return render(request, 'modelForm_user_lisst.html' , {'users': users}) class UserEdit(View): def get(self, request, uid): user_data = models.UserInfo.objects.filter(id=uid).first() print('数据查询:', type(user_data)) # 将数据库查询出来的数据对象 user_html_obj = UserInfoModelForm(instance=user_data) return render(request, 'ModelForm_user_edit.html', {'user_html_obj': user_html_obj, 'uid': uid}) pass def post(self, request,uid): user = models.UserInfo.objects.filter(id=uid).first() mf_obj = UserInfoModelForm(request.POST, instance=user) # mf_obj = UserInfoModelForm(request.POST) # 更新的数据符合要求,保存到数据库 if mf_obj.is_valid(): print(mf_obj.cleaned_data) mf_obj.save() if mf_obj.cleaned_data.get('rember_login'): # 记住登录用户xxx时间内免登陆,设置cookie ,session等 print('是否记住登录:', mf_obj.cleaned_data.get('rember_login')) else: print(mf_obj.errors.as_json) return render(request, 'ModelForm_user_edit.html', {'user_html_obj': mf_obj, 'uid': uid})
posted on 2020-07-30 14:54 zhangmingda 阅读(1107) 评论(0) 编辑 收藏 举报