Django中的Form表单验证
回忆一下Form表单验证的逻辑:
前端有若干个input输入框,将用户输入内容,以字典传递给后端。
后端预先存在一个Form表单验证的基类,封装了一个检测用户输入是否全部通过的方法。该方法会先定义好错误信息的字典,并会遍历类的所有属性(对应前端待验证的输入域),调用各自的验证方法,将错误信息(两类,必要与否以及格式正确与否)存入字典,并得出最终的验证结果。在使用时,需要定义继承自Form基类不同的Form类,以对应有着不同输入域的Form表单。在拿到前端给的字典前,要先初始化自定义From类,直接执行封装好的整体验证方法,拿到结果后就可以抛给前端了。
Django中Form表单验证涉及到的知识:
1.Django中的ErrorDcit类如何封装了错误信息
# project/app01/forms.py from django import forms # 继承自Django的Form类 # 内部以字段形式定义验证域 class MyForm(forms.Form): user = forms.CharField() pwd = forms.CharField()
# project/app01/views.py def form(request): from app01.forms import MyForm if request.method == 'POST': f = MyForm(request.POST) ret = f.is_valid() # bool data = f.cleaned_data # {'user': 'asd', 'pwd': 'asd'} errors = f.errors # ErrorDict,打印时因为__str__方法,会显示位ul标签的形式 print(errors.get('user', None)[0] if errors.get('user', None) else None) # ErrorList,以索引取出第一条错误信息 return render(request, "form.html", {"errors": f.errors}) return render(request, "form.html")
# project/templates/forms.html <form action="/form/" method="post"> <div> 用户名:<input type="text" name="user"/> </div> <div> 密码:<input type="password" name="pwd"/> </div> <div> <input type="submit" value="提交"/> </div> {{ errors }} <div></div>
2.抛给前端的ErrorDcit及使用模板语言漂合理展示
展示错误信息的前端布局
通过返回Form类和模板语言在前端动态生成input标签
# project/app01/views.py def form(request): from app01.forms import MyForm empty_form = MyForm() if request.method == 'POST': f = MyForm(request.POST) if f.is_valid(): print(f.cleaned_data) # 这里只是为了使得正确提交后不至于让input消失,实际坏境中这里应该是用户信息验证 return render(request, "form.html", {'myform': empty_form}) return render(request, "form.html", {"errors": f.errors, "myform": f}) else: return render(request, "form.html", {'myform': empty_form})
# project/templates/forms.html <head> <meta charset="UTF-8"> <title>Title</title> <style> .input-group{ padding: 15px; } .input-group input{ width: 200px; } .input-group span{ display: inline-block; position: relative; border: 1px solid red; top: 25px; left: -211px; } </style> </head> <body> <form action="/form/" method="post"> <div class="input-group"> <div style="float:left;width:70px;">用户名:</div> {{ myform.user }} {% if errors.user.0 %} <span>{{ errors.user.0 }}</span> {% endif %} </div> <div class="input-group"> <div style="float:left;width:70px;">密码:</div> {{ myform.pwd }} {% if errors.pwd.0 %} <span>{{ errors.pwd.0 }}</span> {% endif %} </div> <div> <input style="float:left;margin-left:15px;" type="submit" value="提交"/> </div> </form>
4.django.forms中的CharField参数
(required, min/max_length,error_messages,forms.widget)
不重启服务时数据库数据动态更新到前端(静态字段的特点)
field不合需求时自定义验证规则(validators参数)
# project/app01/forms.py from django import forms from app01 import models def mobile_validate(value): import re mobile_re = re.compile("^(13[0-9]|14[579]|15[0-3,5-9]|1 6[6]|17[0135678]|18[0-9]|19[89])\\d{8}$") if not mobile_re.match(value): print('123123') raise forms.ValidationError('手机号码格式不对哦') class MyForm(forms.Form): def __init__(self, *args, **kwargs): super(MyForm, self).__init__(*args, **kwargs) self.fields['book_type'] = forms.CharField( widget=forms.Select(choices=models.BookType.objects.values_list('id', 'caption')) ) user = forms.CharField(min_length=4, max_length=10, widget=forms.TextInput) pwd = forms.CharField(error_messages={'required': '为什么不输入密码??'}) email = forms.EmailField(error_messages={'required': '邮箱还没输入哦', 'invalid': '邮箱格式错误'}) # book_type_choices = ( # (0, '小说'), value # (1, '科普'), innerText # ) # 元组内有元组 # 从数据库获得数据 # 注意这里filed都是静态字段 # 类的静态字段只创建一次以后不会再修改,新的对象都会使用同一份数据 # 所以MyForm这里的静态字段只会执行一次 # 加入数据库中的数据更新了,服务器不重启的话,这里从数据库取来的值是不会变的 # 因此将该字段写入类的初始化方法里,不要忘了执行父类的初始化方法哦 # book_type_choices = models.BookType.objects.values_list('id', 'caption') # book_type = forms.CharField( # widget=forms.Select(choices=book_type_choices) # ) comment = forms.CharField( widget=forms.Textarea(attrs={'style': 'border:1px solid red;'}) ) # 可以为生成的标签添加属性 mobile = forms.CharField( validators=[mobile_validate, ], error_messages={'required': '手机号不填不行'}, widget=forms.TextInput )
<div class="input-group"> <div style="float:left;width:70px;">用户名:</div> {{ myform.user }} {% if errors.user.0 %} <span>{{ errors.user.0 }}</span> {% endif %} </div> <div class="input-group"> <div style="float:left;width:70px;">密码:</div> {{ myform.pwd }} {% if errors.pwd.0 %} <span>{{ errors.pwd.0 }}</span> {% endif %} </div> <div class="input-group"> <div style="float:left;width:70px;">邮箱:</div> {{ myform.email }} {% if errors.email.0 %} <span>{{ errors.email.0 }}</span> {% endif %} // 以下都是上面input-group标签的重复,只是field不同而已,不再细说
碎碎念:
中间给render传入两个字典,一直调试不出问题,费时颇久,下次留心。