Django 用户认证 用户 邮箱登录 邮箱注册 ORM or,and,not form.py FORM ModelForm Paginator 分页 HTMl JQuery 定位元素 ajax django切片 restfulapi 跨域 Ubantu Python Mysql Scrapy 爬虫 导出 Python读写 Pycharm 破解 session re sqlit3 生成式 其他 Prism 富文本 CSS Nginx 部署 请求头 抓包 协议 selenium Ubuntu 宝塔 AI Comfy-ui ollama dify open-webui Git docker
django重写form表单中的局部钩子函数
张建行 2022年1月25日 11:57 50 文章标签: Django 邮箱登录 邮箱注册 ORM FORM ModelForm

注意:重写钩子方法时方法名为 - clena_字段名(self): 即可

from django import forms
from django.core.exceptions import ValidationError
from jax import models
 
 
class RegForm(forms.Form):
    username = forms.CharField(
        max_length=16,
        label="用户名",
        error_messages={
            "max_length": "用户名最长16位",
            "required": "用户名不能为空!",
        },
        widget=forms.TextInput(
            attrs={"class":"form-control", "placeholder": "用户名"},
        )
    )
 
    password = forms.CharField(
        min_length=6,
        label="密码",
        error_messages={
            "required": "密码不能为空",
            "min_length": "密码不能少于6位",
        },
        widget = forms.PasswordInput(
            attrs={"class": "form-control", "placeholder": "密码"},
        )
    )
 
    re_password = forms.CharField(
        min_length=6,
        label="确认密码",
        error_messages={
            "required": "密码不能为空",
            "min_length": "密码不能少于6位",
        },
        widget=forms.PasswordInput(
            attrs={"class": "form-control", "placeholder": "密码"},
        )
    )
 
    email = forms.EmailField(
        label="邮箱",
        error_messages={
            "invalid": "请输入正确的邮箱格式",
            "required": "邮箱不能为空",
        },
        widget=forms.EmailInput(
            attrs={"class": "form-control", "placeholder": "邮箱"},
        )
    )
 
    # 重写全局的钩子函数,对确认密码做校验
    def clean(self):
        password = self.cleaned_data.get("password")
        re_password = self.cleaned_data.get("re_password")
 
        if re_password and re_password != password:
            self.add_error("re_password", ValidationError("两次密码不一致"))
 
        else:
            return self.cleaned_data
 
    # 重写username局部钩子
    def clean_username(self):
        username = self.cleaned_data.get("username")
        is_exist = models.UserInfo.objects.filter(username=username)
        if is_exist:
            self.add_error("username", ValidationError("该用户已经存在!"))
        else:
            return username
 
    # 重写email局部钩子
    def clean_email(self):
        email = self.cleaned_data.get("email")
        is_exist = models.UserInfo.objects.filter(email=email)
        if is_exist:
            self.add_error("email", ValidationError("该邮箱已经注册!"))
        else:
            return email

django的form表单中定义的字段,都有对应的id以及方法,例如id_username、clean_username,这里的方法均为django中forms.Form源码类BaseForm定义

例:

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
        self.data = {} if data is None else data
        self.files = {} if files is None else files
        self.auto_id = auto_id
        if prefix is not None:
            self.prefix = prefix
        self.initial = initial or {}
        self.error_class = error_class
        # Translators: This is the default suffix added to form field labels
        self.label_suffix = label_suffix if label_suffix is not None else _(':')
        self.empty_permitted = empty_permitted
        self._errors = None  # Stores the errors after clean() has been called.
 
        # The base_fields class attribute is the *class-wide* definition of
        # fields. Because a particular *instance* of the class might want to
        # alter self.fields, we create self.fields here by copying base_fields.
        # Instances should always modify self.fields; they should not modify
        # self.base_fields.
        self.fields = copy.deepcopy(self.base_fields)
        self._bound_fields_cache = {}
        self.order_fields(self.field_order if field_order is None else field_order)
 
 
    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)
    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
 
    def has_changed(self):
        """Return True if data differs from initial."""
        return bool(self.changed_data)