Django Form验证
在实际的生产环境中比如登录和验证的时候,我们一般都使用Jquery+ajax来判断用户的输入是否为空,假如JS被禁用的话,咱们这个认证屏障是不是就消失了呢?(虽然一般不会禁用掉但是还是存在风险)所以我们一般做两种认证一种是前端做一遍认证,在后端做一遍认证。
如果前端中要涉及到很多input,提交到后台,后台要一一取出,分别做验证,这是件很痛苦的事。
def register(request): if request.method == "POST": ret = {"status":False,"msg":""} u = request.POST.get('user',None) e = request.POST.get('email',None) p = request.POST.get('password',None) p2 = request.POST.get('password2',None) #这里有个问题,如果,这个from表单有20个input,你在这里是不是的取20次? count = models.UserInfo.objects.filter(user=u).count() if count == 0: if p == p2: print("注册成功") models.UserInfo.objects.create(user=u, email=e, password=p) data_list = models.UserInfo.objects.all() ret["status"] = True ret["msg"] = "注册成功,请登录" return HttpResponse(json.dumps(ret)) # return redirect('/index/') else: print('diff') ret["msg"] = "两次输入密码不一致" return HttpResponse(json.dumps(ret)) elif len(u) > 0 and count >= 1: print('用户名已经存在' ) ret["msg"] = "用户名已经存在" return HttpResponse(json.dumps(ret)) else: return render( request, 'cmdb/register.html', ) #验证: #输入不能为空,并且有的可以为空有的不可以为空 #如果email = xxxx 这样合法吗 ''' 你在这里是不是需要做一大堆的输入验证啊?并且有很多这种页面会存在这种情况,如果每个函数都这样做估计就累死了 ''' if request.method == 'GET': return render( request, 'cmdb/register.html', )
在样能解决这个问题呢?通过Django的form来实现,其他语言也有叫做(模型绑定)
Django的form的作用:
1、生成html标签
2、用来做用户提交的验证
1、生成html标签
views
from django import forms class LoginForm(forms.Form): user = forms.CharField(required=True, error_messages={'required': '用户名不能为空.'}) pwd = forms.CharField(required=True, min_length=6, max_length=10, error_messages={'required': '密码不能为空.', 'min_length': "至少6位"}) num = forms.IntegerField(error_messages={'required': '数字不能空.','invalid': '必须输入数字'}) phone = forms.CharField(validators=[mobile_validate, ],) test = forms.CharField(widget=forms.Textarea(attrs={'class': 'c1'})) def login(request): if request.POST: objPost = LoginForm(request.POST) ret = objPost.is_valid() # print(objPost) print(ret) if ret: print(objPost.clean()) else: from django.forms.utils import ErrorDict #print(type(obj.errors),obj.errors.as_json()) # obj1.errors print(objPost.errors.as_json()) return render(request, 'login.html',{'obj1': objPost}) else: objGet = LoginForm() return render(request, 'login.html',{'obj1': objGet})
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .error-msg{ color: red; } </style> </head> </head> <body> <form action="/app01/login/" method="POST"> <div> <div> {{ obj1.user }} {% if obj1.errors.user %} <span class="error-msg">{{ obj1.errors.user.0 }}</span> {% endif %} </div> <div> {{ obj1.pwd }} <span class="error-msg">{{ obj1.errors.pwd.0 }}</span> </div> <div> {{ obj1.num }} <span class="error-msg">{{ obj1.errors.num.0 }}</span> </div> <div> {{ obj1.phone }} <span class="error-msg">{{ obj1.errors.phone.0 }}</span> </div> <div> {{ obj1.test }} <span class="error-msg">{{ obj1.errors.test.0 }}</span> </div> <input type="submit" value="提交"> </div> </form> </body> </html>
2、简单的form表单验证用户输入的内容
def login(request): if request.POST: #获取用户输入一句话就搞定 objPost = LoginForm(request.POST) ''' 咱们把post过来的数据当参数传给LoginForm咱们定义的这个类,LoginForm会自动会去你提交的数据 user/pwd/num/phone 自动的封装到objPost里,封装到这个对象里我们就可以判断输入是否合法 ''' ret = objPost.is_valid() # print(objPost) print(ret) if ret: print(objPost.clean()) else: from django.forms.utils import ErrorDict #print(type(obj.errors),obj.errors.as_json()) # obj1.errors print(objPost.errors.as_json()) return render(request, 'login.html',{'obj1': objPost})#然后把对象传给html else: objGet = LoginForm() #创建了这个对象 return render(request, 'login.html',{'obj1': objGet}) from django.views.decorators.csrf import csrf_exempt,csrf_protect
当我们输入不合法的时候,(在创建类设置的需求)为空、或者不是email格式的时候!
这样在后端我们是不是就有一套验证的机制?就可以通过is_valid()来判断用户输入是否合法!如果不合法就把返回信息发送过去,如果合法获取数据操作即可!
捕获错误信息并返回
from django import forms class LoginForm(forms.Form): user = forms.CharField(required=True, error_messages={'required': '用户名不能为空.'}) pwd = forms.CharField(required=True, min_length=6, max_length=10, error_messages={'required': '密码不能为空.', 'min_length': "至少6位"}) num = forms.IntegerField(error_messages={'required': '数字不能空.','invalid': '必须输入数字'}) phone = forms.CharField(validators=[mobile_validate, ],) test = forms.CharField(widget=forms.Textarea(attrs={'class': 'c1'}))
def login(request): if request.POST: #获取用户输入一句话就搞定 objPost = LoginForm(request.POST) ''' 咱们把post过来的数据当参数传给LoginForm咱们定义的这个类,LoginForm会自动会去你提交的数据 user/pwd/num/phone 自动的封装到objPost里,封装到这个对象里我们就可以判断输入是否合法 ''' ret = objPost.is_valid() # print(objPost) print(ret) if ret: print(objPost.clean()) #通过验证,获取提交的数据 ''' {'user': 'asfd', 'num': 1, 'pwd': 'dsafss', 'test': '32', 'phone': '13331525685'} ''' else: from django.forms.utils import ErrorDict #print(type(obj.errors),obj.errors.as_json()) # obj1.errors print(objPost.errors) ''' <ul class="errorlist"><li>phone<ul class="errorlist"><li>手机号码格式错误</li></ul></li></ul> ''' return render(request, 'login.html',{'obj1': objPost})#然后把对象传给html,在把错误信息传递过去 else: objGet = LoginForm() #创建了这个对象 return render(request, 'login.html',{'obj1': objGet})#然后把对象传给html
html标签,使用 login 中定义的obj1 对应的errors输出
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> .error-msg{ color: red; } </style> </head> </head> <body> <form action="/app01/login/" method="POST"> <div> <div> {{ obj1.user }} {% if obj1.errors.user %} <span class="error-msg">{{ obj1.errors.user.0 }}</span> {% endif %} </div> <div> {{ obj1.pwd }} <span class="error-msg">{{ obj1.errors.pwd.0 }}</span> </div> <div> {{ obj1.num }} <span class="error-msg">{{ obj1.errors.num.0 }}</span> </div> <div> {{ obj1.phone }} <span class="error-msg">{{ obj1.errors.phone.0 }}</span> </div> <div> {{ obj1.test }} <span class="error-msg">{{ obj1.errors.test.0 }}</span> </div> <input type="submit" value="提交"> </div> </form> </body> </html>
这样如果,我都按照要求提交,就可以取到数据了?这样咱们就不用自己去拿数据是
{'user': 'asfd', 'num': 1, 'pwd': 'dsafss', 'test': '32', 'phone': '13331525685'}
3、form表单定制化
3.1、自定义报错内容
在form里有一个参数:error_messages 在他这里就可以定义报错内容
class UserInfo(forms.Form): email = forms.EmailField(required=True,error_messages={'required':u'邮箱不能为空'}) #required是否可以为空,如果为False说明可以为空 host = forms.CharField(error_messages={'required':u'主机不能为空'}) #如果required不写默认为Ture port = forms.CharField(error_messages={'required':u'端口不能为空'}) mobile = forms.CharField(error_messages={'required':u'手机不能为空'}, widget=forms.TextInput(attrs={'class':'form-control','placeholder':u'手机号码'})#给input添加属性 #这里默认是TextInput,标签 )
效果:
3.2给userinfo增加一个备注
class UserInfo(forms.Form): email = forms.EmailField(required=True,error_messages={'required':u'邮箱不能为空'}) #required是否可以为空,如果为False说明可以为空 host = forms.CharField(error_messages={'required':u'主机不能为空'}) #如果required不写默认为Ture port = forms.CharField(error_messages={'required':u'端口不能为空'}) #默认mobile里有一个默认为空的机制,我们在原有的参数里增加怎们自定义的方法 mobile = forms.CharField(validators=[mobile_validate,],#应用咱们自己定义的规则 error_messages={'required':u'手机不能为空'}, widget=forms.TextInput(attrs={'class':'form-control','placeholder':u'手机号码'}) #这里默认是TextInput,标签 ) #咱们在新增一个备注 memo = forms.CharField(required=False, widget=forms.Textarea(attrs={'class':'form-control','placeholder':u'备注'}) )
效果如下:
3.3 生成select标签
class UserInfo(forms.Form): email = forms.EmailField(required=True,error_messages={'required':u'邮箱不能为空'}) #required是否可以为空,如果为False说明可以为空 host = forms.CharField(error_messages={'required':u'主机不能为空'}) #如果required不写默认为Ture port = forms.CharField(error_messages={'required':u'端口不能为空'}) #默认mobile里有一个默认为空的机制,我们在原有的参数里增加怎们自定义的方法 mobile = forms.CharField(validators=[mobile_validate,],#应用咱们自己定义的规则 error_messages={'required':u'手机不能为空'}, widget=forms.TextInput(attrs={'class':'form-control','placeholder':u'手机号码'}) #这里默认是TextInput,标签 ) #咱们在新增一个备注 memo = forms.CharField(required=False, widget=forms.Textarea(attrs={'class':'form-control','placeholder':u'备注'}) ) user_type_choice = ( (0, u'普通用户'), (1, u'高级用户'),) user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,attrs={'class':'form-control'}))
3.4、关于后端验证
这个后端验证是必须要有验证机制的,前端可以不写但是后端必须要写!前端的JS是可以被禁用掉到。
3.5 Django 优化错误信息显示
设置显示error的样式
error_msg = user_input_obj.errors.as_data()#这里原来什么都没写,默认是ul的样式,默认是as_ul(),如果我们写成as_data()返回的就是一个原生的字符串 #还有一个as_json
实例:
import re from django import forms 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 UserInfo(forms.Form): user_type_choice = ( (0, u'普通用户'), (1, u'高级用户'),) user_type = forms.IntegerField(widget=forms.widgets.Select(choices=user_type_choice,attrs={'class':'form-control'})) email = forms.EmailField(required=True,error_messages={'required':u'邮箱不能为空'}) #required是否可以为空,如果为False说明可以为空 host = forms.CharField(error_messages={'required':u'主机不能为空'}) #如果required不写默认为Ture port = forms.CharField(error_messages={'required':u'端口不能为空'}) #默认mobile里有一个默认为空的机制,我们在原有的参数里增加怎们自定义的方法 mobile = forms.CharField(validators=[mobile_validate,],#应用咱们自己定义的规则 error_messages={'required':u'手机不能为空'}, widget=forms.TextInput(attrs={'class':'form-control','placeholder':u'手机号码'}) #这里默认是TextInput,标签 ) #咱们在新增一个备注 memo = forms.CharField(required=False, widget=forms.Textarea(attrs={'class':'form-control','placeholder':u'备注'}))
def user_list(request): obj = UserInfo() #创建了这个对象 if request.method == 'POST': #获取用户输入一句话就搞定 user_input_obj = UserInfo(request.POST) if user_input_obj.is_valid(): #判断用户输入是否合法 data = user_input_obj.clean() #获取用户输入 print(data) else: #如果发生错误,捕捉错误 error_msg = user_input_obj.errors.as_data()#这里原来什么都没写,默认是ul的样式,默认是as_ul(),如果我们写成as_data()返回的就是一个原生的字符串 #还有一个as_json print(error_msg) #打印一下然后看下他的类型 #然后把错误信息返回 return render(request,'user_list.html',{'obj':obj,'errors':error_msg,})#然后把对象传给html,在把错误信息传递过去 return render(request,'user_list.html',{'obj':obj,})#然后把对象传给html
html
{% load mytag %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Shuai</title> </head> <body> <form action="/app01/user_list/" method="post"> <p>用户类型:{{ obj.user_type }}<span>{% error_message errors.user_type %}</span></p> <p>主机:{{ obj.host }}<span>{% errors.host %}</span></p> <p>端口:{{ obj.port }}<span>{% error_message errors.port %}</span></p> <p>邮箱:{{ obj.email }}<span>{% error_message errors.email %}</span></p> <p>手机:{{ obj.mobile }}<span>{% error_message errors.mobile %}</span></p> <p>备注:{{ obj.memo }}<span>{% error_message errors.memo %}</span></p> <input type="submit" value="submit"/> </form> </body> </html>
来源:https://www.cnblogs.com/jasonwang-2016/p/5864691.html