首先,我们看看能正常验证两次密码一致性的注册表单 :
from __future__ import unicode_literals
import unicodedata
from django import forms
from django.contrib.auth import (
authenticate, get_user_model, password_validation,
)
from django.forms.widgets import TextInput
class UsernameField(forms.CharField):
def to_python(self, value):
return unicodedata.normalize('NFKC', super(UsernameField, self).to_python(value))
class UserRegisterForm(forms.ModelForm):
"""
学生注册表单
"""
password1 = forms.CharField(
label="确认密码",
widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '请输入确认密码'}),
strip=False,
help_text="请输入确认密码")
password2 = forms.CharField(
label="确认密码",
widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '请输入确认密码'}),
strip=False,
help_text="请输入确认密码",
)
class Meta:
model = User
fields = ("username",)
field_classes = {'username': UsernameField}
widgets = {
'username': TextInput(attrs={'class': 'form-control', 'placeholder': '请输入您的姓名'}),
}
def clean_password2(self):
password1 = self.cleaned_data.get("password1")
password2 = self.cleaned_data.get("password2")
print("p2---\n",type(password2), password2)
if password1 and password2 and password1 != password2:
raise forms.ValidationError("两次密码不一致")
# self.instance.username = self.cleaned_data.get('username')
# password_validation.validate_password(self.cleaned_data.get('password2'), self.instance)
return password2
本段代码链接:https://gitee.com/yinzhuoqun/StudentsManager/blob/master/students/views.py
假设现在把上面的 UserRegisterForm 表单的 clean_password2 改成 clean_password1 后,form.is_valid() 验证的时候会出现什么现象呢?
答案是:会出现两次密码的一致性验证失效,这到底是为啥?在代码里的表现就是,在 clean_password1 里面 get password2 的值是空的,跳过了密码一致性验证的逻辑。
System check identified no issues (0 silenced).
March 06, 2020 - 18:47:27
Django version 2.2.7, using settings 'StudentsManager.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.
p2---
{'username': '张4全', 'password1': 'django123456'}
p2 <class 'NoneType'> None
[06/Mar/2020 18:47:36] "POST /register HTTP/1.1" 200 2192
查询 django 文档 有这么几句话:
我的理解是,还没被 clean() 验证的字段不会放入到 cleaned_data 中, 当要验证码 该字段时才放入到 cleaned_data 中。这样就会导致没验证 password2 时,在验证 clean_password1 中 password2 的值为 None.
Django 表单验证的源码剖析: