一:自定义匹配规则案例-注册-局部钩子
实现目标:用户名不能重复、密码不能是纯数字
数据库表结构
class UserInfo(models.Model): name=models.CharField(max_length=32) pwd=models.CharField(max_length=32) email=models.CharField(max_length=32)
后端代码
1:匹配规则
from django import forms from app01.models import UserInfo from django.core.exceptions import NON_FIELD_ERRORS, ValidationError #错误管理 from django.forms import widgets #widgets魔法工具包 class UserForm(forms.Form): #创建校验规则类。,必须继承forms组件类 name=forms.CharField(min_length=5,label="用户名") pwd=forms.CharField(label="密码") email=forms.EmailField(label="邮箱") # 自定义钩子(匹配规则) # 用户名不能重复 def clean_name(self): val=self.cleaned_data.get('name') #先取值 ret=UserInfo.objects.filter(name=val) #查看数据库中是否有这个值 if not ret: #如果在数据库中没有,就通过匹配 return val else:#否则,说明在数据库中有该用户名 raise ValidationError("用户名已存在") # 密码不能是纯数字 def clean_pwd(self): val = self.cleaned_data.get('pwd') # 先取值 print(type(val)) if val.isdigit(): #判断是否是数字 raise ValidationError("密码不能是纯数字") else: return val
2:视图函数
def reg(request): if request.method=='POST': form=UserForm(request.POST) #把数据放在规则类里校验 if form.is_valid():#校验数据 UserInfo.objects.create(**form.cleaned_data) #符合规则后我们把数据插入到数据库中,因为数据是字典,所以需要打散 else: error=form.errors return render(request,'reg.html',locals()) #把错误数据渲染到模板 else: form=UserForm() #没有把我们输入的数据放进去查看是否匹配规则。我们的目的是把UserForm规则类的字段渲染到页面 return render(request,'reg.html',locals())
前端代码
<form action="" method="post" novalidate> {% csrf_token %} {% for field in form %} <div> <label for="">{{ field.label }}</label> {# 显示字段名:#} {{ field }}{# 显示input框:#} <span class="error">{{ field.errors }}</span> {# 显示错误信息:#} </div> {% endfor %} <input type="submit"> </form>
效果:
二:自定义匹配规则案例-注册-全局钩子
1:实现目标:
需要 确认密码 和 密码 进行比对。
2:数据库表结构
class UserInfo(models.Model): name=models.CharField(max_length=32) pwd=models.CharField(max_length=32) r_pwd=models.CharField(max_length=32) email=models.CharField(max_length=32)
3:后端代码
from django import forms from app01.models import UserInfo from django.core.exceptions import NON_FIELD_ERRORS, ValidationError #错误管理 from django.forms import widgets #widgets魔法工具包 class UserForm(forms.Form): name=forms.CharField(min_length=5,label="用户名") pwd=forms.CharField(label="密码") r_pwd=forms.CharField(label="确认密码") email=forms.EmailField(label="邮箱") # 自定义局部钩子 # 用户名不能重复 def clean_name(self): val=self.cleaned_data.get('name') ret=UserInfo.objects.filter(name=val) if not ret: return val else: raise ValidationError("用户名已存在") # 密码不能是纯数字 def clean_pwd(self): val = self.cleaned_data.get('pwd') print(type(val)) if val.isdigit(): raise ValidationError("密码不能是纯数字") else: return val def clean(self):#全局钩子 pwd=self.cleaned_data.get("pwd") #有可能第一层校验未通过取值是空 r_pwd=self.cleaned_data.get("r_pwd") print("=======>") if pwd and r_pwd: #如果两个都通过了第一层说明clean_data中有值就是true if pwd==r_pwd: print(1111) return self.cleaned_data else: print(222222) raise ValidationError("两次密码不一致") else: #如果两个不在clean_data里,那就没必要在比较了,因为本身就已经在errors里了 return self.cleaned_data
视图函数
def reg(request): if request.method=='POST': form=UserForm(request.POST) if form.is_valid():#校验数据 UserInfo.objects.create(**form.cleaned_data) else: error=form.errors if form.errors.get("__all__"):#第二层全局错误,__all__:全局错误信息 g_error=form.errors.get("__all__")[0] return render(request,'reg.html',locals()) #把错误数据渲染到模板 else: form=UserForm() return render(request,'reg.html',locals())
4:前端代码
<form action="" method="post" novalidate> {% csrf_token %} {% for field in form %} <div> <label for="">{{ field.label }}</label> {# 显示字段名:#} {{ field }}{# 显示input框:#} <span class="error">{{ field.errors }}</span> {# 显示错误信息:#} {% if field.label == "确认密码" %} <span>{{ g_error|default:"" }}</span> {% endif %} </div> {% endfor %} <input type="submit"> </form>
5:效果
三:Forms组件自定义规则函数(钩子)----源码分析
从上面的案例中我们知道了如何自定义一个钩子函数,那么为什么是那样写的呢?
这一切都在源码中有定义------>参看源码分析:博文 Django-源码-Forms组件--自定义规则(钩子)