Django之form组件
一、简介 |
web框架中避免不了对表单的验证,我们可以通过js在表单数据提交前做一次校验,然而在Django中form组件不仅仅提供验证功能,还可以生成HTML,还可以与model结合使用,等等强大的功能。
先了解下主要的作用:
- 生成HTML标签
- 验证用户数据(显示错误信息)
- HTML Form提交保留上次提交数据
- 初始化页面显示内容
二、基本操作 |
1.创建form类
#_*_ coding:utf-8 _*_ #Author:wd from django.forms import Form from django.forms import widgets from django.forms import fields class myform(Form): user=fields.CharField( #字段名字一定要和模板中html中input中name属性一致才能验证 widget=widgets.TextInput(attrs={'id':'a1','class':'c1'}), #设置生成hmtl的样式 min_length=6, error_messages={'required':'用户名不能为空','min_length':'用户名至少6位'} ) pwd=fields.CharField( widget=widgets.PasswordInput(), max_length=24, error_messages={'required':'密码不能为空','max_length':'密码长度不能超过24'} ) email=fields.EmailField( error_messages={'required':'用户名不能为空','invalid':'邮箱格式不正确'} ) #校验时候出现的错误提示信息
2.views函数处理
from .cmdbforms import myform #导入定义的form类 def fm(request): if request.method=='GET': obj=myform() #生成对象 return render(request,'form.html',{'obj':obj})#将对象传入到模板中用于生成html elif request.method=='POST': obj=myform(request.POST) if obj.is_valid(): #该方法验证post提交表单的数据是否合法,合法返回True或者否则Flase print(obj.clean()) #获取post表单中提交的数据,格式为字典,可以直接用于model操作数据库 print(obj.cleaned_data)#获取post表单中提交的数据,格式为字典,可以直接用于model操作数据库 return redirect('/cmdb/fm/') else: print(obj.errors) print(obj.errors.as_json())#json格式的错误 return render(request,'form.html',{'obj':obj})#当出现错误的时候返回的错误信息
3.HTML模板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/cmdb/fm/" method="POST" enctype="multipart/form-data"> {% csrf_token %} <p>{{ obj.user }} {{ obj.user.errors.0 }}</p> {# 0代表第一个错误,在这里就是错误的字符串 #} <p>{{ obj.pwd }} {{ obj.pwd.errors.0 }}</p> <p>{{ obj.email }} {{ obj.email.errors.0 }}</p> <input type="submit" value="提交"/> </form> </body> </html>
三、form类中的字段和插件介绍 |
创建Form类时,主要涉及到字段(fields)和插件(widgets),字段用于对用户请求数据的验证,插件用于自动生成HTML。
1、Django内置字段
Field required=True, 是否允许为空 widget=None, HTML插件 label=None, 用于生成Label标签或显示内容(使用用户名密码时候,使用) initial=None, 初始值(默认值) help_text='', 帮助信息(在标签旁边显示) error_messages=None, 错误信息 {'required': '不能为空', 'invalid': '格式错误'} show_hidden_initial=False, 是否在当前插件后面再加一个隐藏的且具有默认值的插件(可用于检验两次输入是否一直) validators=[], 自定义验证规则 localize=False, 是否支持本地化,示例场景:utc时间和本地时间转化 disabled=False, 是否可以编辑 label_suffix=None Label内容后缀 CharField(Field) max_length=None, 最大长度 min_length=None, 最小长度 strip=True 是否移除用户输入空白 IntegerField(Field) max_value=None, 最大值 min_value=None, 最小值 FloatField(IntegerField) ... DecimalField(IntegerField) max_value=None, 最大值 min_value=None, 最小值 max_digits=None, 总长度 decimal_places=None, 小数位长度 BaseTemporalField(Field) input_formats=None 时间格式化 DateField(BaseTemporalField) 格式:2015-09-01 TimeField(BaseTemporalField) 格式:11:12 DateTimeField(BaseTemporalField)格式:2015-09-01 11:12 DurationField(Field) 时间间隔:%d %H:%M:%S.%f ... RegexField(CharField) regex, 自定制正则表达式 max_length=None, 最大长度 min_length=None, 最小长度 error_message=None, 忽略,错误信息使用 error_messages={'invalid': '...'} EmailField(CharField) ... FileField(Field) allow_empty_file=False 是否允许空文件,文件也在clean_data里 ImageField(FileField) ... 注:需要PIL模块,pip3 install Pillow 以上两个字典使用时,需要注意两点: - form表单中 enctype="multipart/form-data" - view函数中 obj = MyForm(request.POST, request.FILES) URLField(Field) ... BooleanField(Field) ... NullBooleanField(BooleanField) ... ChoiceField(Field) ... choices=(), 选项,如:choices = ((0,'上海'),(1,'北京'),) required=True, 是否必填 widget=None, 插件,默认select插件 label=None, Label内容 initial=None, 初始值 help_text='', 帮助提示 ModelChoiceField(ChoiceField) ... django.forms.models.ModelChoiceField queryset, # 查询数据库中的数据 empty_label="---------", # 默认空显示内容 to_field_name=None, # HTML中value的值对应的字段 limit_choices_to=None # ModelForm中对queryset二次筛选 ModelMultipleChoiceField(ModelChoiceField) #多选 ... django.forms.models.ModelMultipleChoiceField TypedChoiceField(ChoiceField) coerce = lambda val: val 对选中的值进行一次转换 empty_value= '' 空值的默认值 MultipleChoiceField(ChoiceField) ... TypedMultipleChoiceField(MultipleChoiceField) coerce = lambda val: val 对选中的每一个值进行一次转换 empty_value= '' 空值的默认值 ComboField(Field) fields=() 使用多个验证,如下:即验证最大长度20,又验证邮箱格式 fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),]) MultiValueField(Field) PS: 抽象类,只能被继承,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用 SplitDateTimeField(MultiValueField) input_date_formats=None, 格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y'] input_time_formats=None 格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M'] FilePathField(ChoiceField) 文件选项,目录下文件显示在页面中 path, 文件夹路径 match=None, 正则匹配 recursive=False, 递归下面的文件夹 allow_files=True, 允许文件 allow_folders=False, 允许文件夹 required=True, widget=None, label=None, initial=None, help_text='' GenericIPAddressField protocol='both', both,ipv4,ipv6支持的IP格式 unpack_ipv4=False 解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用 SlugField(CharField) 数字,字母,下划线,减号(连字符) ... UUIDField(CharField) uuid类型 ... 注:UUID是根据MAC以及当前时间等创建的不重复的随机字符串
2、Django内置插件
TextInput(Input)
NumberInput(TextInput)
EmailInput(TextInput)
URLInput(TextInput)
PasswordInput(TextInput)
HiddenInput(TextInput)
Textarea(Widget)
DateInput(DateTimeBaseInput)
DateTimeInput(DateTimeBaseInput)
TimeInput(DateTimeBaseInput)
CheckboxInput
Select
NullBooleanSelect
SelectMultiple
RadioSelect
CheckboxSelectMultiple
FileInput
ClearableFileInput
MultipleHiddenInput
SplitDateTimeWidget
SplitHiddenDateTimeWidget
SelectDateWidget
3、常用插件示例
# 单radio,值为字符串 # user = fields.CharField( # initial=2, # widget=widgets.RadioSelect(choices=((1,'上海'),(2,'北京'),)) # ) # 单radio,值为字符串 # user = fields.ChoiceField( # choices=((1, '上海'), (2, '北京'),), # initial=2, # widget=widgets.RadioSelect # ) # 单select,值为字符串 # user = fields.CharField( # initial=2, # widget=widgets.Select(choices=((1,'上海'),(2,'北京'),)) # ) # 单select,值为字符串 # user = fields.ChoiceField( # choices=((1, '上海'), (2, '北京'),), # initial=2, # widget=widgets.Select # ) # 多选select,值为列表 # user = fields.MultipleChoiceField( # choices=((1,'上海'),(2,'北京'),), # initial=[1,], # widget=widgets.SelectMultiple # ) # 单checkbox # user = fields.CharField( # widget=widgets.CheckboxInput() # ) # 多选checkbox,值为列表 # user = fields.MultipleChoiceField( # initial=[2, ], # choices=((1, '上海'), (2, '北京'),), # widget=widgets.CheckboxSelectMultiple # )
四、初始化数据 |
很多时候,我们在一个页面上做增删改查的时候,需要从数据库中将数据拿出来并在页面渲染,那么这些默认值可以使用form直接生成在页面上
方法一:定义form字段中使用initial参数初始化默认选项,但是该默认值不能动态配置(当数据库中选项变化时候,该默认值不会改变)
1.form类定义
#!/usr/bin/env python3 #_*_ coding:utf-8 _*_ #Author:wd from django.forms import fields from django.forms import widgets from django.forms import Form from django.core.validators import RegexValidator class appfm(Form): user=fields.CharField() city=fields.ChoiceField( choices=((1, '上海'), (2, '北京'),(3, '上海')), widget=widgets.Select ) gender=fields.ChoiceField( initial=[2,], #多选的默认值是一个列表,单选是一个数字 choices=((1, '男'), (2, '女'),), widget=widgets.CheckboxSelectMultiple(), #多选插件 )
2、views函数处理
from .myform import appfm def test(request): user_dict={ 'user':'wd', 'city':2, 'gender':1, } if request.method=='GET': obj=appfm(user_dict)#将用户信息传入form对象,最后直接用于获取页面的默认值 return render(request,'test.html',{'obj':obj})
3、html模版
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {{ obj.user }}{{ obj.user.errors.0 }} {{ obj.city }}{{ obj.city.errors.0 }} {{ obj.gender }}{{ obj.gender.errors.0 }} </body> </html>
方法二:重写form构造方法,在实例化时候设置默认值(该方法是动态的),form定义如下:
class appfm(Form): user=fields.CharField() city=fields.ChoiceField( initial=[1,], choices=((1, '上海'), (2, '北京'),(3, '上海')), widget=widgets.SelectMultiple ) def __init__(self,*args,**kwargs): super(appfm,self).__init__(*args,**kwargs) self.initial["city"]=[1,2] #多选为列表,单选为数字
五、form操作动态select标签 |
场景:当我们在数据库中增加一条数据时候,使用form生成的html标签中的select表现需要是最新数据,所以我们需要在渲染模板之前再次从数据库中获取最新数据。
方式一:form实例化之后,通过修改生成的form对象中封装的choices字段重新赋值,确保是当前最新数据,示例:
form定义
#!/usr/bin/env python3 #_*_ coding:utf-8 _*_ #Author:wd from django.forms import Form from django.forms import widgets from django.forms import fields from cmdb import models class myform(Form): user=fields.CharField( #字段名字一定要和模板中html中input中name属性一致才能验证 widget=widgets.TextInput(attrs={'id':'a1','class':'c1'}), min_length=6, error_messages={'required':'用户名不能为空','min_length':'用户名至少6位'} ) pwd=fields.CharField( widget=widgets.PasswordInput(), max_length=24, error_messages={'required':'密码不能为空','max_length':'密码长度不能超过24'} ) email=fields.EmailField( error_messages={'required':'用户名不能为空','invalid':'邮箱格式不正确'} ) #校验时候出现的错误提示信息 user_type=fields.ChoiceField( choices=models.Usertype.objects.values_list('id','name'), #初始化数据 widget=widgets.Select, )
views函数
from .cmdbforms import myform #导入定义的form类 def fm(request): if request.method=='GET': obj=myform() #生成form对象 obj.fields['user_type'].choices=models.Usertype.objects.values_list('id','name')#form对象中的fields字段封装了我们所定义的验证字段,此时我们从数据库拿到最新的数据,赋值给select标签字段就达到了目的了 return render(request,'form.html',{'obj':obj})#将对象传入到模板中用于生成html
html模板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/cmdb/fm/" method="POST" enctype="multipart/form-data"> {% csrf_token %} <p>{{ obj.user }} {{ obj.user.errors.0 }}</p> {# 0代表第一个错误,在这里就是错误的字符串#} <p>{{ obj.pwd }} {{ obj.pwd.errors.0 }}</p> <p>{{ obj.email }} {{ obj.email.errors.0 }}</p> <p>{{ obj.user_type }}</p> <input type="submit" value="提交"/> </form> </body> </html>
方式二:实例化之前,通过重新构造方法,使得每一次的实例化都获得最新的数据
form定义
#!/usr/bin/env python3 #_*_ coding:utf-8 _*_ #Author:wd from django.forms import Form from django.forms import widgets from django.forms import fields from cmdb import models class myform(Form): user=fields.CharField( #字段名字一定要和模板中html中input中name属性一致才能验证 widget=widgets.TextInput(attrs={'id':'a1','class':'c1'}), min_length=6, error_messages={'required':'用户名不能为空','min_length':'用户名至少6位'} ) pwd=fields.CharField( widget=widgets.PasswordInput(), max_length=24, error_messages={'required':'密码不能为空','max_length':'密码长度不能超过24'} ) email=fields.EmailField( error_messages={'required':'用户名不能为空','invalid':'邮箱格式不正确'} ) #校验时候出现的错误提示信息 user_type=fields.ChoiceField( #第一种定义方式 choices=[], widget=widgets.Select, ) user_type1=fields.CharField(widget=widgets.Select(choices=[])) #第二种方式定义 def __init__(self,*args,**kwargs): super(myform,self).__init__(*args,**kwargs) self.fields['user_type'].choices = models.Usertype.objects.values_list('id', 'name')#按照第一种方式定义获取 self.fields['user_type1'].widget.choices=models.Usertype.objects.values_list('id', 'name')#按照第二种方式定义获取
views函数
def fm(request): if request.method=='GET': obj=myform() #生成form对象 return render(request,'form.html',{'obj':obj})#将对象传入到模板中用于生成html
html模板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/cmdb/fm/" method="POST" enctype="multipart/form-data"> {% csrf_token %} <p>{{ obj.user }} {{ obj.user.errors.0 }}</p> {# 0代表第一个错误,在这里就是错误的字符串#} <p>{{ obj.pwd }} {{ obj.pwd.errors.0 }}</p> <p>{{ obj.email }} {{ obj.email.errors.0 }}</p> <p>{{ obj.user_type }}</p> <p>{{ obj.user_type1 }}</p> <input type="submit" value="提交"/> </form> </body> </html>
方式三:通过ModelChoiceField、ModelMultipleChoiceField(多选)字段进行自动获取最新数据,但是需要在model定义时候,自定义str方法,用于显示select标签选项。
model定义
#!/usr/bin/env python3 #_*_ coding:utf-8 _*_ #Author:wd from django.forms import Form from django.forms import widgets from django.forms import fields from django.forms import ModelChoiceField from cmdb import models class myform(Form): user=fields.CharField( #字段名字一定要和模板中html中input中name属性一致才能验证 widget=widgets.TextInput(attrs={'id':'a1','class':'c1'}), min_length=6, error_messages={'required':'用户名不能为空','min_length':'用户名至少6位'} ) pwd=fields.CharField( widget=widgets.PasswordInput(), max_length=24, error_messages={'required':'密码不能为空','max_length':'密码长度不能超过24'} ) email=fields.EmailField( error_messages={'required':'用户名不能为空','invalid':'邮箱格式不正确'} ) #校验时候出现的错误提示信息 user_type2=ModelChoiceField( queryset=models.Usertype.objects.all(), empty_label="请选择", #多出一项提示语,默认是"---------" to_field_name='id',#生成的select标签中value的值 )
form定义
#!/usr/bin/env python3 #_*_ coding:utf-8 _*_ #Author:wd from django.forms import Form from django.forms import widgets from django.forms import fields from django.forms import ModelChoiceField from cmdb import models class myform(Form): user=fields.CharField( #字段名字一定要和模板中html中input中name属性一致才能验证 widget=widgets.TextInput(attrs={'id':'a1','class':'c1'}), min_length=6, error_messages={'required':'用户名不能为空','min_length':'用户名至少6位'} ) pwd=fields.CharField( widget=widgets.PasswordInput(), max_length=24, error_messages={'required':'密码不能为空','max_length':'密码长度不能超过24'} ) email=fields.EmailField( error_messages={'required':'用户名不能为空','invalid':'邮箱格式不正确'} ) #校验时候出现的错误提示信息 user_type2=ModelChoiceField( queryset=models.Usertype.objects.all(), empty_label="请选择", #多出一项提示语,默认是"---------" )
view函数
def fm(request): if request.method=='GET': obj=myform() #生成form对象 return render(request,'form.html',{'obj':obj})#将对象传入到模板中用于生成html
html模板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="/cmdb/fm/" method="POST" enctype="multipart/form-data"> {% csrf_token %} <p>{{ obj.user }} {{ obj.user.errors.0 }}</p> {# 0代表第一个错误,在这里就是错误的字符串#} <p>{{ obj.pwd }} {{ obj.pwd.errors.0 }}</p> <p>{{ obj.email }} {{ obj.email.errors.0 }}</p> <p>{{ obj.user_type }}</p> <p>{{ obj.user_type1 }}</p> <p>{{ obj.user_type2 }}</p> <input type="submit" value="提交"/> </form> </body> </html>
六、form内置钩子 |
在form验证的方法中,form验证提供了is_vaild方法进行验证,在这个方法中其实提供了许多的钩子让我们可以自定义验证。
Django1.11版本源码中验证is_vaild内部验证流程为:
obj.is_vaild-->self.errors-->self.full_clean-->self._clean_fields-->self._clean_form-->slef._post_clean,其中我们可以自己根据内置钩子进行验证。
1、self_clean_fields():字段正则表达式验证,里面会执行“clean_字段”方法,我们可以通过自定义该方法对字段进行单独验证。
示例:
form定义
class RegisterForm(Form): username=fields.CharField() email=fields.EmailField() def clean_username(self): #验证username字段,名字必须为clean_username c=models.user.objects.filter(name=self.cleaned_data['username']).count() if not c: return self.cleaned_data['username'] #通过,将该字段数据返回 else: raise ValidationError('用户名已经存在',code='232')#不通过则抛出异常 def clean_email(self): return self.cleaned_data['email']
views函数
def register(request): if request.method=="GET": obj=myform.RegisterForm() return render(request,'register.html',{'obj':obj}) if request.method=="POST": obj1=myform.RegisterForm(request.POST) if obj1.is_valid():#执行内部验证方法 print(obj1.cleaned_data) return redirect('/app01/register/') else: print(obj1.errors.as_json()) return render(request, 'register.html', {'obj': obj1}) # 当出现错误的时候返回的错误信息
2、self._clean_form:对整体字段进行验证,执行该方法时候会执行self.clean()方法,所以通过定义self.clean()方法,可以对字段进行整体验证。
tips:当使用_clean_form进行整体验证的时候错误信息放在了errors中的__all__或者NON_FIELD_ERRORS(from django.core.exceptions import NON_FIELD_ERRORS)字段里面。
class LoginForm(Form): username=fields.CharField() pwd=fields.CharField() def clean(self): c=models.user.objects.filter(name=self.cleaned_data['username'], pwd=self.cleaned_data['pwd']).count() if c : return self.cleaned_data #将正确结果返回 else: raise ValidationError('用户名或者密码错误')
3、slef._post_clean:还可以再一次进行验证,定义方法同self.clean()
class LoginForm(Form): username=fields.CharField() pwd=fields.CharField() def _post_clean(self): pass
六、自定义验证规则 |
方式一:
from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.validators import RegexValidator class MyForm(Form): user = fields.CharField( validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')], )
方式二:
import re from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.exceptions import ValidationError # 自定义验证规则 def mobile_validate(value): mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$') if not mobile_re.match(value): raise ValidationError('手机号码格式错误') class PublishForm(Form): title = fields.CharField(max_length=20, min_length=5, error_messages={'required': '标题不能为空', 'min_length': '标题最少为5个字符', 'max_length': '标题最多为20个字符'}, widget=widgets.TextInput(attrs={'class': "form-control", 'placeholder': '标题5-20个字符'})) # 使用自定义验证规则 phone = fields.CharField(validators=[mobile_validate, ], error_messages={'required': '手机不能为空'}, widget=widgets.TextInput(attrs={'class': "form-control", 'placeholder': u'手机号码'})) email = fields.EmailField(required=False, error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'}, widget=widgets.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'}))
方式三:自定义方法
from django import forms from django.forms import fields from django.forms import widgets from django.core.exceptions import ValidationError from django.core.validators import RegexValidator class FInfo(forms.Form): username = fields.CharField(max_length=5, validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.', 'invalid')], ) email = fields.EmailField() def clean_username(self): """ Form中字段中定义的格式匹配完之后,执行此方法进行验证 :return: """ value = self.cleaned_data['username'] if "666" in value: raise ValidationError('666已经被玩烂了...', 'invalid') return value
方式四:同时生成多个标签进行验证
from django.forms import Form from django.forms import widgets from django.forms import fields from django.core.validators import RegexValidator ############## 自定义字段 ############## class PhoneField(fields.MultiValueField): def __init__(self, *args, **kwargs): # Define one message for all fields. error_messages = { 'incomplete': 'Enter a country calling code and a phone number.', } # Or define a different message for each field. f = ( fields.CharField( error_messages={'incomplete': 'Enter a country calling code.'}, validators=[ RegexValidator(r'^[0-9]+$', 'Enter a valid country calling code.'), ], ), fields.CharField( error_messages={'incomplete': 'Enter a phone number.'}, validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid phone number.')], ), fields.CharField( validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.')], required=False, ), ) super(PhoneField, self).__init__(error_messages=error_messages, fields=f, require_all_fields=False, *args, **kwargs) def compress(self, data_list): """ 当用户验证都通过后,该值返回给用户 :param data_list: :return: """ return data_list ############## 自定义插件 ############## class SplitPhoneWidget(widgets.MultiWidget): def __init__(self): ws = ( widgets.TextInput(), widgets.TextInput(), widgets.TextInput(), ) super(SplitPhoneWidget, self).__init__(ws) def decompress(self, value): """ 处理初始值,当初始值initial不是列表时,调用该方法 :param value: :return: """ if value: return value.split(',') return [None, None, None]
七、form内置序列化错误信息 |
1、使用django自带的序列化serializers函数,这个方法缺点是函数内部序列化为什么内容就返回什么内容,不能自定制。
from django.core import serializers ret = models.BookType.objects.all() data = serializers.serialize("json", ret)
2、使用json自定义endocoder进行序列化操作
原理是:通过cls参数制定处理的类,每一次序列化操作都会调用该类中的default方法。
有些时候我们使用json.dumps方法序列化操作时候,并不能完全序列化,会报错,比如,在数据datetime日期时候,此时我们可以通过自定义序列化类来处理
#!/usr/bin/env python3 #_*_ coding:utf-8 _*_ #Author:wd import json from datetime import date from datetime import datetime a={'k1':"v1",'date':datetime.now()} class JsonCustomEncoder(json.JSONEncoder): #自定义处理类 def default(self, field): if isinstance(field, datetime): return field.strftime('%Y-%m-%d %H:%M:%S') elif isinstance(field, date): return field.strftime('%Y-%m-%d') else: return json.JSONEncoder.default(self, field) b=json.dumps(a,cls=JsonCustomEncoder) print(b)
应用场景:ajax提交数据时候,Django进行数据验证返回给的错误数据时候使用,示例:
def fm(request): if request.method=='GET': obj=myform() #生成form对象 return render(request,'form.html',{'obj':obj})#将对象传入到模板中用于生成html elif request.method=='POST': obj=myform(request.POST) if obj.is_valid(): #该方法验证post提交表单的数据是否合法,合法返回True或者否则Flase print(obj.clean()) #获取post表单中提交的数据,格式为字典,可以直接用于model操作数据库 print(obj.cleaned_data)#获取post表单中提交的数据,格式为字典,可以直接用于model操作数据库 return redirect('/cmdb/fm/') else: #######自定义序列化类进行错误序列化### from django.core.exceptions import ValidationError import json class JsonCustomEncoder(json.JSONEncoder): def default(self, field): if isinstance(field, ValidationError): return {'code':field.code,'message':field.messages} else: return json.JSONEncoder.default(self, field) ret={'status':None,'message':None,'code':None} ret['error']=obj.errors.as_data() res=json.dumps(ret,cls=JsonCustomEncoder) return HttpResponse(res)