django模型提供类似于表单'clean_ <fieldname>()?</fieldname>的东西

时间:2012-03-21 23:36:20

标签: django django-models django-validation django-forms

我正在尝试将所有与业务逻辑相关的验证移到模型中,而不是将它们保留在表单中。但在这里我有一个棘手的情况,我喜欢与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>()形式的东西。如果没有,你会把这个验证逻辑放在哪里?为什么?

2 个答案:

答案 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
相关问题