Django: переопределение метода clean() в формах-вопрос о возникновении ошибок

Я делал такие вещи в чистом методе:

if self.cleaned_data['type'].organized_by != self.cleaned_data['organized_by']:
      raise forms.ValidationError('The type and organization do not match.')
if self.cleaned_data['start'] > self.cleaned_data['end']:
      raise forms.ValidationError('The start date cannot be later than the end date.')

но тогда это означает, что форма может поднять только одну из этих ошибок за раз. Есть ли способ для формы поднять обе эти ошибки?

правка #1: Любые решения для вышеизложенного великолепны, но хотелось бы что-то, что также будет работать в сценарии, таком как:

if self.cleaned_data['type'].organized_by != self.cleaned_data['organized_by']:
      raise forms.ValidationError('The type and organization do not match.')
if self.cleaned_data['start'] > self.cleaned_data['end']:
      raise forms.ValidationError('The start date cannot be later than the end date.')
super(FooAddForm, self).clean()

где FooAddForm является ModelForm и имеет уникальные ограничения, которые также могут вызвать ошибки. Если кто-нибудь знает о чем-то подобном, это было бы здорово...

4 ответов


документы:

https://docs.djangoproject.com/en/1.7/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other

from django.forms.util import ErrorList

def clean(self):

  if self.cleaned_data['type'].organized_by != self.cleaned_data['organized_by']:
    msg = 'The type and organization do not match.'
    self._errors['type'] = ErrorList([msg])
    del self.cleaned_data['type']

  if self.cleaned_data['start'] > self.cleaned_data['end']:
    msg = 'The start date cannot be later than the end date.'
    self._errors['start'] = ErrorList([msg])
    del self.cleaned_data['start']

  return self.cleaned_data

errors = []
if self.cleaned_data['type'].organized_by != self.cleaned_data['organized_by']:
      errors.append('The type and organization do not match.')
if self.cleaned_data['start'] > self.cleaned_data['end']:
     errors.append('The start date cannot be later than the end date.')

if errors:
    raise forms.ValidationError(errors)

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

msg = 'The type and organization do not match.'
self._errors['__all__'] = ErrorList([msg])

кроме того, как объясняют документы Django: "если вы хотите добавить новую ошибку в конкретное поле, вы должны проверить, существует ли ключ в self._errors или нет. Если нет, создайте новую запись для данного ключа, удерживая пустую ErrorList экземпляра. В любом случае вы можете добавить сообщение об ошибке в Список для поля имя в вопросе, и он будет отображаться при отображении формы."


хотя его старый пост, если вы хотите меньше кода, Вы можете использовать add_error() метод добавления сообщений об ошибках. Я расширяю ответ @kemar, чтобы показать используемый случай:

add_error() автоматически удаляет поле из словаря cleaned_data, вам не нужно удалять его вручную. Также вам не нужно ничего импортировать, чтобы использовать это.

документация здесь

def clean(self):

  if self.cleaned_data['type'].organized_by != self.cleaned_data['organized_by']:
    msg = 'The type and organization do not match.'
    self.add_error('type', msg)

  if self.cleaned_data['start'] > self.cleaned_data['end']:
    msg = 'The start date cannot be later than the end date.'
    self.add_error('start', msg)

  return self.cleaned_data