我正在尝试将所有与业务逻辑相关的验证移到模型中,而不是将它们保留在表单中。但在这里我有一个棘手的情况,我喜欢与SO社区协商。
在我的SignupForm(模型表单)中,我进行了以下特定于字段的验证,以确保输入的电子邮件不存在。
def clean_email(self):
email = self.cleaned_data['email']
if ExtendedUser.objects.filter(email=email).exists():
raise ValidationError('This email address already exists.')
return email
如果我要将此验证移到模型中,根据官方文档,我会将其放在相应模型的clean()
ExtendedUser
中。但该文件还提到了以下内容:
将存储Model.clean()引发的任何ValidationError异常 在使用的特殊键错误字典键NON_FIELD_ERRORS中 对于与整个模型而不是特定模型相关的错误 字段
这意味着,使用clean()
,我无法将从中提出的错误与特定字段相关联。我想知道模型是否提供类似于'clean_<fieldname>()
形式的东西。如果没有,你会把这个验证逻辑放在哪里?为什么?
答案 0 :(得分:3)
您可以将清洁方法转换为validator
,并在声明字段时将其包括在内。
另一种选择是对模型字段进行子类化并覆盖其干净方法。
但是,对于表单,您没有直接等同于定义clean_<field name>
方法。您甚至无法将错误分配给各个字段as you can do for forms
答案 1 :(得分:1)
如评论中所述,我认为您应该在模型级别处理此验证。如果您仍然觉得最好更接近模型,并且因为它们无法更改,我会建议直接在数据库级别进行更改:
ALTER TABLE auth_user ADD UNIQUE (email)
在没有猴子修补身份验证的情况下,将unique=True
约束添加到User
模型的方法很糟糕。
根据要求,我认为应该通过继承基础模型来完成自定义不同表单的好方法。 django-registration中有一个很好的例子。唯一的区别是,而不是从forms.Form
继承的父表单,你将使它成为一个modelForm:
class MyBaseModelForm(ModelForm):
class Meta:
model = MyModel
然后你可以继承它并从这个基础模型中创建不同的形式:
class OtherFormWithCustomClean(MyBaseModelForm):
def clean_email(self):
email = self.cleaned_data['email']
if ExtendedUser.objects.filter(email=email).exists():
raise ValidationError('This email address already exists.')
return email