【问题标题】:Django modelform remove "required" attribute based on other field choiceDjango modelform 根据其他字段选择删除“必需”属性
【发布时间】:2011-10-28 21:12:21
【问题描述】:

我有几个字段的 ModelForm。有些字段是必需的,有些则不是。我也有不同选择的 Select 字段,我想根据这个 Select 字段选择将某些字段设为“必需”或不选择。

我尝试了 Form 的 clean() 方法

def clean(self):
    cleaned_data = self.cleaned_data
    some_field = cleaned_data.get("some_field")
    if some_field == 'some_value':
          self.fields['other_field'].required = False
    return cleaned_data

但它不起作用

【问题讨论】:

    标签: django django-forms django-models


    【解决方案1】:

    如果您想以常用方式打印必填字段的错误消息,您可以这样做:

    def clean(self):
        cleaned_data = super(PasswordChangeForm, self).clean()
        token = cleaned_data.get('token')
        old_password = cleaned_data.get('old_password')
        if not token and not old_password:
            self._errors['old_password'] = self.error_class([self.fields['old_password'].error_messages['required']])
    

    【讨论】:

    • 这个答案非常非常有用!非常感谢!
    【解决方案2】:

    请参阅Cleaning and validating fields that depend on each other 上的 Django 文档。标准做法是改为执行以下处理:

    def clean(self):
        cleaned_data = self.cleaned_data
        some_field = cleaned_data.get("some_field")
        if some_field == 'some_value':
              # 'other_field' is conditionally required.
              if not cleaned_data['other_field']:
                  raise forms.ValidationError("'Other_field' is required.")
        return cleaned_data
    

    【讨论】:

    • 谢谢。这个想法帮助我得到了它!
    • 我需要做类似的验证(Django 1.4),但我正在测试的字段是只读的,所以我的clean_data中没有它(顺便说一句 - 我在管理员中做)。知道如何访问这个只读字段的值吗? 10x
    • 找到了解决办法——form.instance保存了所有相关数据,修改后的数据包含在form.changed_data中
    • 虽然这听起来像是正确的方法,但我认为检查some_field == some_value 的逻辑可以在视图中重复。不知道什么是正确的方法?忍受冗余还是将此验证移至查看?
    • @buffer:我不明白为什么视图需要重复验证逻辑,因为表单已经这样做了。如果视图有类似的检查(以确定是否使用other_field),在两遍系统(1 遍验证,1 遍消费)AFAICT 中无法避免。如果您愿意,您可以只将该逻辑移动到视图中,但是您可以为使用相同表单的多个视图重复相同的逻辑。
    【解决方案3】:

    您的想法是正确的,但问题是各个字段验证在表单清理之前已经运行。你有几个选择。您可以使该字段不需要,并在form.clean 中处理何时需要该字段的逻辑。或者您可以根据需要保留该字段并删除它可能在清理中引发的验证错误。

    def clean(self):
        cleaned_data = self.cleaned_data
        some_field = cleaned_data.get("some_field")
        if some_field == 'some_value':
              if 'other_field' in self.errors:
                  del self.errors['other_field']
                  cleaned_data['other_field'] = None
        return cleaned_data
    

    这有一些问题,因为它删除了 所有 错误,而不仅仅是缺少/必需的错误。 cleaned_data 也有问题。您现在有一个不在cleaned_data 中的必填字段,这就是我将其添加为None 的原因。您的应用程序的其余部分将不得不处理这种情况。有一个没有值的必填字段可能看起来很奇怪。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-26
      • 2016-11-03
      • 1970-01-01
      • 2012-03-08
      • 1970-01-01
      • 1970-01-01
      • 2021-12-13
      • 1970-01-01
      相关资源
      最近更新 更多