Модель формы Django удаляет атрибут «обязательный» на основе выбора другого поля - PullRequest
7 голосов
/ 17 августа 2011

У меня есть ModelForm с несколькими полями. Некоторые поля обязательны для заполнения, некоторые нет. Также у меня есть поле выбора с различными вариантами выбора, и я хочу сделать некоторые поля "обязательными" или не основанными на этом выборе поля выбора.

Я пытался использовать метод 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

но это не работает

Ответы [ 3 ]

10 голосов
/ 17 августа 2011

См. Документацию 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
2 голосов
/ 19 июля 2012

Если вы хотите распечатать сообщение об ошибке для обязательного поля обычным способом, вы можете сделать это:

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 голосов
/ 17 августа 2011

У вас правильная идея, но проблема в том, что проверки отдельных полей уже выполнялись до очистки формы. У вас есть пара вариантов. Вы можете сделать поле не обязательным и обрабатывать логику, когда оно требуется в вашем 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. Остальная часть вашего приложения должна будет обработать этот случай. Может показаться странным иметь обязательное поле, которое не имеет значения.

...