【问题标题】:Returning cleaned_data when overwriting clean() method in Django Model forms在 Django 模型表单中覆盖 clean() 方法时返回 clean_data
【发布时间】:2017-10-06 12:56:34
【问题描述】:

我需要覆盖 Django 模型表单中的 clean() 方法,以对输入的数据执行额外的唯一性检查。

此页面提供了实现细节: https://docs.djangoproject.com/en/1.11/ref/forms/validation/复制到这里:

 def clean(self):
    cleaned_data = super(ContactForm, self).clean()
    cc_myself = cleaned_data.get("cc_myself")
    subject = cleaned_data.get("subject")

    if cc_myself and subject:
        # Only do something if both fields are valid so far.
        if "help" not in subject:
            raise forms.ValidationError(
                "Did not send for 'help' in the subject despite "
                "CC'ing yourself."
            )

但是我很困惑为什么这个方法在函数的末尾没有return cleaned_data?确定这是正确的做法吗?

【问题讨论】:

    标签: python django django-forms


    【解决方案1】:

    看看django的_clean_form方法:

    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
    

    阅读forms doc 的最后一个要点,尤其是ModelForm doc 的这一点。

    如果clean 方法引发ValidationError,则错误将添加到表单的错误中。 如果clean 方法返回了任何内容并且没有抛出任何错误,那么表单将使用它作为cleaned_data 属性。否则它将保留它的“旧”。

    在您的情况下,您的 clean 方法所做的只是验证表单的一个方面。

    【讨论】:

    • 如果我子类化,覆盖.clean(),什么都不返回,然后另一个表单子类化我的子类并尝试做类似的事情,这不是问题吗?当然,他们都应该使用.cleaned_data 而不是super().clean()...
    • @AdamBarnes 是的,这可能是个问题 - docs 也提到了这一点:“示例代码中对 super().clean() 的调用确保父类中的任何验证逻辑维护...”
    【解决方案2】:

    您感兴趣的示例是对相关字段的clean 方法的覆盖。这意味着它验证了涉及多个字段的逻辑。将此视为表单的clean 方法。因此,在这种情况下,您不想返回任何值。

    正如doc 所说:

    “在实践中这样做时要小心,因为它可能会导致表单输出混乱。我们在这里展示了哪些是可能的,并让您和您的设计师来确定在您的特定情况下有效的方法。”

    这取决于您的具体情况,但根据我在一个特定字段上覆盖 clean 的经验,如果验证通过,您将希望返回它。同样,这仅适用于一个字段。

    这是文档中的另一个示例,但用于一个字段验证:

    def clean_recipients(self):
        data = self.cleaned_data['recipients']
        if "fred@example.com" not in data:
            raise forms.ValidationError("You have forgotten about Fred!")
    
        # Always return a value to use as the new cleaned data, even if
        # this method didn't change it.
        return data
    

    【讨论】:

    • “将其视为表单的clean 方法”是什么意思?你说的“这个”是什么?
    • 我想我的问题可能会得到最好的回答,如果我了解在调用 clean() 后还有哪些函数使用返回的“cleaned_data”?或者更确切地说,“cleaned_data”是干什么用的?
    • 对不起,我在你的例子中指的是clean方法。当我说表单的clean 方法时,它仅用于教育目的。我只想强调一个事实,即表单是字段的集合,因此每个都有其 clean` 方法。关注link 并阅读第一段。
    • 好吧,在我看来,这是一个完全不同的问题。如果您期望得到明确的答案,请先提出明确的问题。对不起,我的回答不是你需要的。
    【解决方案3】:

    在 Django form.clean() 需要返回 cleaned_data 的字典。
    此方法可能仍会返回要使用的数据字典,但不再需要它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-21
      • 1970-01-01
      • 2019-03-20
      • 2019-04-19
      • 2020-08-07
      • 1970-01-01
      • 2016-08-05
      相关资源
      最近更新 更多