我正在尝试在网站上使用电子邮件和电话进行注册。用户可以使用电话或电子邮件或两者注册。如果用户将电话和电子邮件字段都清空,则会引发ValidationError
,并且#34;您不能将电话和电子邮件字段留空。您必须填写至少一个字段。"
clean
我们有单独的username, email, phone, password
方法。我不想在save()
上实施上述验证。我也不想在用户模型中定义clean
方法。
我已经为这个表格编写了测试,然后通过了。但是,如果我同时使用clean
和clean_fieldname
,可能会出现什么错误?处理视图时会出现问题吗?
我有3个问题:
clean_fieldname
和clean
方法吗?
形成吗 clean()
和validate()
如何运作?我已经阅读了django文档,但我完全不了解它。这是我实施的代码。
class RegisterForm(SanitizeFieldsForm, forms.ModelForm):
email = forms.EmailField(required=False)
message = _("Phone must have format: +9999999999. Upto 15 digits allowed."
" Do not include hyphen or blank spaces in between, at the"
" beginning or at the end.")
phone = forms.RegexField(regex=r'^\+(?:[0-9]?){6,14}[0-9]$',
error_messages={'invalid': message},
required=False)
password = forms.CharField(widget=forms.PasswordInput())
MIN_LENGTH = 10
class Meta:
model = User
fields = ['username', 'email', 'phone', 'password',
'full_name']
class Media:
js = ('js/sanitize.js', )
def clean(self):
super(RegisterForm, self).clean()
email = self.data.get('email')
phone = self.data.get('phone')
if (not phone) and (not email):
raise forms.ValidationError(
_("You cannot leave both phone and email empty."
" Signup with either phone or email or both."))
def clean_username(self):
username = self.data.get('username')
check_username_case_insensitive(username)
if username.lower() in settings.CADASTA_INVALID_ENTITY_NAMES:
raise forms.ValidationError(
_("Username cannot be “add” or “new”."))
return username
def clean_password(self):
password = self.data.get('password')
validate_password(password)
errors = []
email = self.data.get('email')
if email:
email = email.split('@')
if email[0].casefold() in password.casefold():
errors.append(_("Passwords cannot contain your email."))
username = self.data.get('username')
if len(username) and username.casefold() in password.casefold():
errors.append(
_("The password is too similar to the username."))
phone = self.data.get('phone')
if phone:
if phone_validator(phone):
phone = str(parse_phone(phone).national_number)
if phone in password:
errors.append(_("Passwords cannot contain your phone."))
if errors:
raise forms.ValidationError(errors)
return password
def clean_email(self):
email = self.data.get('email')
if email:
if User.objects.filter(email=email).exists():
raise forms.ValidationError(
_("Another user with this email already exists"))
return email
def clean_phone(self):
phone = self.data.get('phone')
if phone:
if User.objects.filter(phone=phone).exists():
raise forms.ValidationError(
_("Another user with this phone already exists"))
return phone
def save(self, *args, **kwargs):
user = super().save(*args, **kwargs)
user.set_password(self.cleaned_data['password'])
user.save()
return user
答案 0 :(得分:1)
你可以从阅读Django代码中获得很多东西;这是一个评论很好的代码库!相关部分位于django/forms/forms.py。清理/验证表单后,它将调用full_clean
。这将首先调用_clean_fields
,调用字段clean
并在要调用的表单上查找clean_{fieldname}
方法。然后,调用表单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 = {}
# 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()
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_form(self):
try:
cleaned_data = self.clean()
except ValidationError as e:
self.add_error(None, e)
else:
if cleaned_data is not None:
self.cleaned_data = cleaned_data