前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Django form 里 password1 password2 验证先后探索(注册表单)

Django form 里 password1 password2 验证先后探索(注册表单)

作者头像
卓越笔记
发布2023-02-18 14:14:26
7440
发布2023-02-18 14:14:26
举报
文章被收录于专栏:卓越笔记

首先,我们看看能正常验证两次密码一致性的注册表单 :

代码语言:javascript
复制
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 的值是空的,跳过了密码一致性验证的逻辑。

代码语言:javascript
复制
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 文档 有这么几句话:

  • Field子类的clean() 方法。它负责以正确的顺序运行to_python、validate 和 run_validators 并传播它们的错误。如果任何时刻、任何方法引发ValidationError,验证将停止并引发这个错误。这个方法返回验证后的数据,这个数据在后面将插入到表单的 cleaned_data 字典中。
  • 表单子类中的clean_<fieldname>() 方法 —— <fieldname> 通过表单中的字段名称替换。这个方法完成于特定属性相关的验证,这个验证与字段的类型无关。这个方法没有任何传入的参数。你需要查找self.cleaned_data 中该字段的值,记住此时它已经是一个Python 对象而不是表单中提交的原始字符串(它位于cleaned_data 中是因为字段的clean() 方法已经验证过一次数据)。 例如,如果你想验证名为serialnumber 的CharField 的内容是否唯一, clean_serialnumber() 将是实现这个功能的理想之处。你需要的不是一个特别的字段(它只是一个CharField),而是一个特定于表单字段特定验证,并规整化数据。 这个方法返回从cleaned_data 中获取的值,无论它是否修改过。
  • 表单子类的clean() 方法。这个方法可以实现需要同时访问表单多个字段的验证。这里你可以验证如果提供字段A,那么字段B 必须包含一个合法的邮件地址以及类似的功能。 这个方法可以返回一个完全不同的字典,该字典将用作cleaned_data。

我的理解是,还没被 clean() 验证的字段不会放入到 cleaned_data 中, 当要验证码 该字段时才放入到 cleaned_data 中。这样就会导致没验证 password2 时,在验证 clean_password1 中 password2 的值为 None.

Django 表单验证的源码剖析:

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-3-6 19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
验证码
腾讯云新一代行为验证码(Captcha),基于十道安全栅栏, 为网页、App、小程序开发者打造立体、全面的人机验证。最大程度保护注册登录、活动秒杀、点赞发帖、数据保护等各大场景下业务安全的同时,提供更精细化的用户体验。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档