Django modelform remove";“必需”;基于其他字段选择的属性

Django modelform remove";“必需”;基于其他字段选择的属性,django,django-forms,django-models,Django,Django Forms,Django Models,我有几个字段的ModelForm。有些字段是必需的,有些不是。另外,我有不同选择的选择字段,我想根据这个选择字段选择一些字段是否为“必需” 我尝试使用clean()的Form方法 def clean(self): cleaned_data = self.cleaned_data some_field = cleaned_data.get("some_field") if some_field == 'some_value': self.fields['

我有几个字段的ModelForm。有些字段是必需的,有些不是。另外,我有不同选择的选择字段,我想根据这个选择字段选择一些字段是否为“必需”

我尝试使用clean()的Form方法

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

但是它不起作用

您的想法是正确的,但问题是,在表单清理之前,单个字段验证已经运行。你有几个选择。您可以将该字段设置为非必填字段,并在
表单中处理该字段的逻辑。或者,您可以根据需要保留该字段,并删除该字段在清理过程中可能引发的验证错误

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

这会有一些问题,因为它会删除所有错误,而不仅仅是丢失的/必需的错误。清理后的数据也有问题。您现在有一个必填字段,它不在已清理的\u数据中,这就是为什么我将其添加为
None
。应用程序的其余部分将必须处理此情况。有一个没有值的必填字段似乎有些奇怪。

请参阅上的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

如果您希望以常用方式打印必填字段的错误消息,可以执行以下操作:

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']])

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