1、从is_valid方法入手

    def is_valid(self):
    """Return True if the form has no errors, or False otherwise."""
    return self.is_bound and not self.errors

    如果is_valid要返回True的话,那么self.is_bound要为True并且self.errors要为Flase(字面意思上看errors为False的话,表示没有错误信息)

  2、is_bound

    以下代码出现在BaseForm类中,也就是Form的父类(Form继承了父类的初始化方法)

    def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
     initial=None, error_class=ErrorList, label_suffix=None,
    empty_permitted=False, field_order=None, use_required_attribute=None, renderer=None):
    self.is_bound = data is not None or files is not None

    is_bound为True的条件是data不为None,或者files不为None

    也就是说在初始化一个Form对象时,只要传入了data或者files,那么is_bound的属性就一定为True

    在调用is_valid方法校验数据之前,肯定需要将POST提交的数据用来初始化一个Form对象,然后调用该方法对数据进行校验

    所以,只要是用来校验POST提交的数据时,is_bound肯定为True    

      form_obj = RegForm(request.POST)  # 包含用户提交的数据的From对象
      if form_obj.is_valid(): # 对数据进行校验
      return HttpResponse('ok')

  3、errors

    @property
    def errors(self):
    """Return an ErrorDict for the data provided for the form."""
    if self._errors is None:
    self.full_clean()
    return self._errors

    errors实际上是一个方法,只是使用property装饰器装饰成了属性,可以通过对象.属性名的方式调用

    当self._errors为None时会执行,full_clean方法。然后最终返回_errors。

    _errors同样定义在BaseForm的初始化方法内,初始化即为None,但是最终返回却将它作为结果返回。

    那么,说明full_clean内部肯定对_errors做了修改

    直接看full_clean方法内部做了些什么

  4、full_clean() 

    def full_clean(self):
    """
    Clean all of self.data and populate self._errors and self.cleaned_data.
    """
    self._errors = ErrorDict() # 错误字典(初始化为空字典)
    if not self.is_bound: # Stop further processing.
    return
    self.cleaned_data = {} # 创建了cleaned_data字典,用于后续存放结果校验无误的数据
    # If the form is permitted to be empty, and none of the form data has
    # changed from the initial data, short circuit any validation.
    if self.empty_permitted and not self.has_changed():
    return

    self._clean_fields()
    self._clean_form()
    self._post_clean()

    该方法首先赋值了一个错误字典给_errors(前面提到,初始化时为None),也就是说再经过一系列校验后,如果最后该字典为空,那么说明没有错误,即校验通过。

    接着往下看。

    如果is_bound为False直接终止方法执行,也就是该Form对象内没有数据,不需要校验。

    然后创建了一个字典cleaned_data,用于存放后续校验无误的数据。

    从这就可以知道,一个form对象只有在使用了is_valid()方法后,内部才会生成cleaned_data字典。使用is_valid()之前没有该变量。

    然后接着看后续调用校验方法的过程。

  5、_clean_fields() 

    def _clean_fields(self):
    for name, field in self.fields.items():
    # value_from_datadict() gets the data from the data dictionaries.
    # Each widget type knows how to retrieve its own data, because some
    # widgets split data over several HTML fields.
    if field.disabled:
    value = self.get_initial_for_field(field, name)
    else:
    value = field.widget.value_from_datadict(self.data, self.files, self.add_prefix(name))
     try:
    if isinstance(field, FileField):
    initial = self.get_initial_for_field(field, name)
    value = field.clean(value, initial)
    else:
    value = field.clean(value)
    self.cleaned_data[name] = value
    if hasattr(self, 'clean_%s' % name):
    value = getattr(self, 'clean_%s' % name)()
    self.cleaned_data[name] = value
    except ValidationError as e:
    self.add_error(name, e) # 将捕获到的异常添加到错误字典中

    该方法内部,直接对fields进行迭代取值处理。

    fields内部存放的就是表单提交的数据,以字典形式存放,name对应的就是Form类中定义的属性名,field就是一个字段对象。

    如果当前迭代到的字段对象对应的input被禁用的话(disableed为True),那么就以该input的初始值作为该字段的值(initial设置的值。如果没有设置,得到的则是空字符串)。

    反之,该字段的值就是用户输入的值。

    

    接着,判断当前迭代到的字段对象类型,如果是文件类型,则使用文件相关的校验方式

    其他类型,都使用else代码块里的校验方式

    def clean(self, value):
    """
    Validate the given value and return its "cleaned" value as an
    appropriate Python object. Raise ValidationError for any errors.
    """
    value = self.to_python(value)
    self.validate(value)
    self.run_validators(value)
    return value

    validate(value)方法,即校验当前字段的值是否为空,如果为空则抛出required的提示信息(字段为必填项时会进行该校验)

    run_validators方法,执行的是当前字段默认的校验器(如果是Email字段,则它的默认校验器就会校验字段的值是否符合正确的邮箱格式)以及自定义的校验器(即设置字段的参数validators时,传入的自定义的校验函数对象)

    如果校验过程中出现异常,会层层抛出,每一层都在捕获异常,最终会将捕获到的异常添加到错误字段中。

    except ValidationError as e:
    self.add_error(name, e)

    然后最终返回原值。如果上述校验无误,则将该值添加到cleaned_data字典内。

    接着,判断有没有该字段的局部钩子函数,对该字段进行校验。

    有的话,就调用这个局部钩子就要该字段的值,校验无误就将该值重新赋值一遍给cleaned_data。出现异常就会抛出,执行异常处理函数,将错误信息添加到错误字典,并将该字段的值从cleaned_data字典内删除。

    从这也就能知道,局部钩子函数的返回值必须是对应字段的值原样返回,否则即使校验通过,在赋值时也会出错,导致最终得到的值不对。

   总结:

    clean方法主要功能就是执行字段内置校验方法、字段内置校验器以及自定义校验器

    _clean_fields方法只要功能就是执行clean、以及局部钩子函数,对数据进行校验。

  

  6、_clean_form()

    执行全局的钩子函数

    全局钩子函数 ,返回值必须是cleaned_data

    def clean(self):
    """
    Hook for doing any extra form-wide cleaning after Field.clean() has been
    called on every field. Any ValidationError raised by this method will
    not be associated with a particular field; it will have a special-case
    association with the field named '__all__'.
    """
    return self.cleaned_data

    因为,自定义的全局钩子函数,实际上就是重写了上述方法,最终返回值必须和上述方法用于,即校验无误的数据字典

  总结:

    整个is_valid()的主要的流程为:

      1、执行full_clean方法

        先定义一个错误字典用户后续判断校验是否正确,

        还有一个cleaned_data存放后续校验无误的数据

      2、执行_clean_fields方法

        该方法对数据进行除了全局钩子函数以外的校验

        先执行字段内置校验方法、字段内置校验器以及自定义校验器对数据进行校验

        然后执行局部钩子函数对数据进行校验

      3、执行_clean_form方法

        该方法对数据进行全局钩子函数的校验

    所有校验执行的先后顺序:

      字段内置的校验方法——>字段内置校验器——>字段自定义的校验器——>局部钩子函数——>全局钩子函数

  

    

django—Form组件校验方法(is_valid)执行流程的更多相关文章

  1. Python - Django - form 组件校验功能

    app01/models.py: from django.db import models class UserInfo(models.Model): username = models.CharFi ...

  2. python3开发进阶-Django框架中form的查看校验方法is_valid()的源码,自定义验证方法

    form表单的校验方法is_valid() 点开我们发现这个函数里面只有两个方法方法,最终返回True or False 我们点进.is_bound属性,里面判断传输的数据不是空和上传文件不是空 点进 ...

  3. Django---FORM组件.FORM组件的字段,FORM组件校验流程,FORM组件的全局和局部钩子,FORM和Model的组合

    Django---FORM组件.FORM组件的字段,FORM组件校验流程,FORM组件的全局和局部钩子,FORM和Model的组合 一丶FORM的介绍 1.生成页面可用的HTML标签 2.对用户提交的 ...

  4. 9.24 Django Form组件

    2018-9-23 20:10:04 这两天优化了自己图书管理系统 github 连接:https://github.com/TrueNewBee/pythonDemo 顺便整理了博客,写了好多总结, ...

  5. django Form组件

    django Form组件 Django的Form主要具有一下几大功能: 生成HTML标签 验证用户数据(显示错误信息) HTML Form提交保留上次提交数据 初始化页面显示内容 小试牛刀 1.创建 ...

  6. django form组件 cookies,session

    django form组件 渲染标签  就是组件里面的字段在前端展示叫做渲染标签 校验数据  用户输入的数据提交给后端组件叫做校验数据 forms组件中定义的字段都是必须传值的(required=Tr ...

  7. Django form组件 与 cookie/session

    目录 一.form组件 二.cookie.session 返回Django 组件 一.form组件 1.1 以注册功能为例 注册功能 1.渲染前端标签获取用户输入 --> 渲染标签 2.获取用户 ...

  8. 6月28日 Django form组件 和 modelform组件

    Form介绍 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比如校验用户是否 ...

  9. Django—Form组件

    Django From简介 我们之前在HTML页面中利用form表单向后端提交数据时,都会写一些获取用户输入的标签并且用form标签把它们包起来. 与此同时我们在好多场景下都需要对用户的输入做校验,比 ...

随机推荐

  1. 关于Mybaits

    mybatis 返回多表多字段用 mybatis 返回多表多字段用 resultType=”java.util.Map”轻松解决问题.不用加什么DTO.这样前端要什么字段就返回什么字段.不用在对多余的 ...

  2. 快速上手spring

    一.初始程序 1.在父类pom导入所需要的jar包 2.编写一个实体类 3.创建一个beans.xml,创建一个bean即创建一个user对象,可在bean内配置property即设置属性值 4.用测 ...

  3. HotSpot VM 中的JIT分类

    在HotSpot VM中内嵌有两个JIT编译器,分别为Client Compiler和Server Compiler,但大多数情况下我们简称为C1编译器和C2编译器.开发人员可以通过如下命令显式指定J ...

  4. Spring Boot 第一弹,问候一下世界!!!

    持续原创输出,点击上方蓝字关注我吧 目录 前言 什么是Spring Boot? 如何搭建一个Spring Boot项目? 第一个程序 Hello World 依赖解读 什么是配置文件? 什么是启动类? ...

  5. 什么是 Opcache,如何使用 Opcache

    Opcode 是啥? 我们先看一下 PHP 的执行过程: PHP 初始化执行环节,启动 Zend 引擎,加载注册的扩展模块. 初始化后读取 PHP 脚本文件,Zend 引擎对 PHP 文件进行词法分析 ...

  6. 【DFIR】数字取证与事件应急响应---初识

    应急响应 适用于负责现场应急,找出可疑的程序,恶意代码的安全工程师.这些可疑恶意程序或代码由另外的专家进行逆向分析. 前言 首先,什么是DRIF? DRIR:Digital Forensics and ...

  7. C语言中 malloc

    参考:https://blog.csdn.net/kokodudu/article/details/11760863 一.malloc()和free()的基本概念以及基本用法: 1.函数原型及说明: ...

  8. Win10系统中文显示乱码怎么解决

    来源:https://jingyan.baidu.com/article/d8072ac4ba20cfec94cefd48.html 简单的说是: 全部设置改为中国而且一定要重启系统,无论时间还是区域 ...

  9. Arduino的外部中断

    Arduino的中断函数格式为attachInterrupt(interrput,function,mode). attachInterrupt函数用于设置外部中断,有3个参数,interrput表示 ...

  10. 【题解】CF1207E XOR Guessing

    Link 这是一道交互题. \(\text{Solution:}\) 观察到猜的数范围只有\(2^{14}.\) 我第一次想到的方法是,我们可以确定系统选择的两个数的异或和,用这个异或和去穷举所有目标 ...