注意:重写钩子方法时方法名为 - 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)