钩子函数(hook)的使用

在源码中:

form_obj.is_valid()都干了什么?


1.self._errors = ErrorDict() --> {}
2.self.cleaned_data = {}

3.self.fields.items()
字段名 字段对象
4.如果有错误:
self._errors["name"] = ""

5.没有报错:
self.cleaned_data["name"] = value(用户填写的值)

一 简介 我们来聊聊如何构建forms的钩子
二 目的 实现自定义的验证机制,从而进行处理
三 分类:
    1 局部钩子 clean_column() 当字段校验完毕后,再进行查找是否有以clean_开头的函数名,如果有,就调用该函数
    2 全局钩子 clean() 其原理是对校验完毕的字段,再进行字段间的校验。当字段校验完毕,查找是否有clean的函数,如果有就运行该函数 
    执行顺序 局部钩子 全局钩子

  

from django.core.exceptions import ValidationError
# 定义局部钩子,用来校验name字段
    def clean_name(self):
        name = self.cleaned_data.get("name", None)
        value = models.UserInfo.objects.filter().values_list("name")
        if name in value:
            raise ValidationError("此名字已经被注册!")
        else:
            return name

    # 定义全局钩子,用来检验密码和确认密码字段是否一致
    # 重写父类的clean方法
    def clean(self):
        # 此时 通过校验的字段的数据都保存在 self.clean_data
        pwd = self.cleaned_data.get("pwd")
        re_pwd = self.cleaned_data.get("re_pwd")
        if pwd == re_pwd:
            return self.cleaned_data
        else:
            self.add_error("re_pwd", ValidationError("两次的密码不一致!"))
            raise ValidationError("两次密码不一致!")

注意
   1 单个字段只能指定单个方法
   2 钩子是按照顺序执行的,如果上面的不过,直接抛出异常了.不会执行下面的钩子
   3 clean()的优先级最高

小补充~~~~~

    1.对于多余的字段不存入库,可以采用字典删除的方式入库

     forms.cleaned_data.pop("column")

     models.object.create(** forms.cleaned_data)

 2. 重新父类init 方法

  

# 重写父类的init方法
    def __init__(self, *args, **kwargs):
        # 1. 批量添加样式
        super().__init__(*args, **kwargs)
        for field in iter(self.fields):
            self.fields[field].widget.attrs.update({
                'class': 'form-control'
            })
        # 2.form对象是一个可迭代的对象
        # choices的数据如果从数据库获取可能会造成数据无法实时更新
        # 通过构造方法,在构造中重新获取数据库中的值
        self.fields["city"].widget.choices = models.City.objects.all().values_list("id", "name")

 

posted @ 2019-07-19 12:34  堪舆先森  阅读(1348)  评论(0编辑  收藏  举报