Django: правильно отображать несколько сообщений об ошибках для одного поля

Я использую Джанго 1.5.5. для моего проекта. У меня есть несколько моделей, некоторые из которых имеют поле «многие ко многим» для другого:

class ScreeningFormat(CorecrmModel):
    name = models.CharField(max_length=100)

class Film(CorecrmModel):
    title = models.CharField(max_length=255)
    screening_formats = models.ManyToManyField(ScreeningFormat)

class Screen(CorecrmModel):
    name = models.CharField(max_length=100)
    screening_formats = models.ManyToManyField(ScreeningFormat)

class FilmShow(CorecrmModel):
    film = models.ForeignKey(Film)
    screen = models.ForeignKey(Screen)
    screening_formats = models.ManyToManyField(ScreeningFormat)

Я создал пользовательскую форму администратора для FilmShow, которая имеет метод clean_screening_formats:

class FilmShowAdminForm(admin.ModelForm):
    def clean_screening_formats(self):
        # Make sure the selected screening format exists in those marked for the film
        screening_formats = self.cleaned_data['screening_formats']
        film_formats = self.cleaned_data['film'].screening_formats.all()
        sf_errors = []
        for (counter, sf) in enumerate(screening_formats):
            if sf not in film_formats:
                sf_error = forms.ValidationError('%s is not a valid screening format for %s' % (sf.name, self.cleaned_data['film'].title), code='error%s' % counter)
                sf_errors.append(sf_error)
        if any(sf_errors):
            raise forms.ValidationError(sf_errors)

        return formats

Фактическая проверка работает нормально, но вывод этих сообщений об ошибках в форме администратора немного отличается. Принимая во внимание, что одно сообщение об ошибке выводится как (например):

This field is required.

Вывод для списка сообщений выглядит следующим образом:

[u'35mm Film is not a valid screening format for Thor: The Dark World']
[u'Blu Ray is not a valid screening format for Thor: The Dark World']

Может ли кто-нибудь предложить, как я могу правильно отображать эти списки сообщений об ошибках?

Изменить: я думаю, что эта проблема возникает из-за того, что django хранит сообщения немного по-другому, когда возникает более одной ошибки. Пример:

>>> from django import forms
>>> error = forms.ValidationError('This is the error message', code='lone_error')
>>> error.messages
[u'This is the error message']

>>> e1 = forms.ValidationError('This is the first error message', code='error1')
>>> e2 = forms.ValidationError('This is the second error message', code='error2')
>>> error_list = [e1, e2]
>>> el = forms.ValidationError(error_list)
>>> el.messages
[u"[u'This is the first error message']", u"[u'This is the second error message']"]

Может ли это быть ошибкой в ​​Django?


person hellsgate    schedule 04.11.2013    source источник
comment
Просто чтобы уточнить: вы ищете обмен сообщениями на уровне поля?   -  person Andrew Sledge    schedule 04.11.2013
comment
Я думаю, что у меня есть обмен сообщениями на уровне поля, я просто хотел бы знать, как вывести несколько из них для одного поля без [u''] вокруг каждого из сообщений   -  person hellsgate    schedule 04.11.2013
comment
Можете ли вы опубликовать часть шаблона, где отображаются сообщения об ошибках?   -  person augustomen    schedule 04.11.2013
comment
Я использую шаблон администратора django по умолчанию, поэтому список ошибок создается из тега шаблона field.field.errors.as_ul. Я обновлю вопрос, добавив немного больше информации   -  person hellsgate    schedule 04.11.2013


Ответы (2)


Реализация, которую вы сделали, действительна только для Django 1.6+. Сравните: документы 1.6 с 1.5.

До версии 1.6 сообщения сразу преобразовывались в строки в django.core.exceptions.ValidationError (см. код здесь):

class ValidationError(Exception):
    """An error while validating data."""
    def __init__(self, message, code=None, params=None):
        import operator
        from django.utils.encoding import force_text
        """
        ValidationError can be passed any object that can be printed (usually
        a string), a list of objects or a dictionary.
        """
        if isinstance(message, dict):
            self.message_dict = message
            # Reduce each list of messages into a single list.
            message = reduce(operator.add, message.values())

        if isinstance(message, list):
            self.messages = [force_text(msg) for msg in message]  #! Will output "u'<message>'"

В вашем случае вместо передачи списка экземпляров ValidationError просто передайте список строк:

>>> e1 = 'This is the first error message'
>>> e2 = 'This is the second error message'
>>> error_list = [e1, e2]
>>> el = forms.ValidationError(error_list)
>>> el.messages
[u'This is the first error message', u'This is the second error message']
person augustomen    schedule 04.11.2013

Это сработало для меня, поэтому продолжайте пробовать следующее:

def clean(self):
if self.acci_anios_residencia == None:
    lista = ["Especifique un año"]
    raise ValidationError({'acci_anios_residencia': lista})
person user5866090    schedule 01.02.2016