【问题标题】:does django models offer something similar to forms' clean_<fieldname>()?django 模型是否提供类似于表单的 clean_<fieldname>() 的功能?
【发布时间】:2012-04-06 13:12:04
【问题描述】:

我正在尝试将所有与业务逻辑相关的验证转移到模型中,而不是将它们留在表单中。但是在这里我遇到了一个棘手的情况,我想咨询 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

如果我要将此验证移至模型,根据官方文档,我会将其放在相应模型ExtendedUserclean() 中。但是文档还提到了以下内容:

Model.clean() 引发的任何 ValidationError 异常都将被存储 在使用的特殊键错误字典键 NON_FIELD_ERRORS 中 对于与整个模型而不是与特定模型相关的错误 字段

这意味着,对于clean(),我无法将由此引发的错误与特定字段相关联。我想知道模型是否提供类似于表单的clean_&lt;fieldname&gt;()。如果不是,你会把这个验证逻辑放在哪里?为什么?

【问题讨论】:

  • 这个逻辑不是和表格有关吗?为什么你认为它住在模型中会更好?在我看来,这将是 django 中模型表单的预期用途。
  • @VascoP - 我只想将所有业务逻辑集中在模型中。一方面,它在设计方面更有条理。从概念上讲,我认为验证存在于模型中是有意义的。此外,当我有多个基于同一模型的模型表单时,它还具有共享相同验证的好处。
  • 您还可以从与给定模型关联的更通用的模型表单继承,并为每个不同的表单设置子模型表单。
  • @VascoP - 我喜欢一般的模型形式方法。请将其添加到您的答案中,我会接受。干杯~
  • 我已经编辑了我的答案以澄清我的意思。是你要找的吗?

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


【解决方案1】:

您可以将您的 clean 方法转换为 validator 并在声明字段时包含它。

另一种选择是子类化模型字段并覆盖其 clean 方法。

但是,没有直接等效于定义clean_&lt;field name&gt; 方法的方法,就像您可以为表单所做的那样。你甚至不能将错误分配给单个字段,as you can do for forms

【讨论】:

    【解决方案2】:

    如评论中所述,我认为您应该在模型表单级别处理此验证。如果您仍然觉得更接近模型会更好,并且由于它们无法更改,我建议直接在 db 级别进行更改:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-06
      • 1970-01-01
      相关资源
      最近更新 更多