Подтвердить что ты не робот

Django - Как указать, в каком поле выполняется проверка?

У меня есть эта модель, которую я показываю на странице администратора:

class Dog(models.Model):
    bark_volume = models.DecimalField(...
    unladen_speed = models.DecimalField(...

    def clean(self):
        if self.bark_volume < 5:
            raise ValidationError("must be louder!")

Как вы можете видеть, я положил валидацию на модель. Но я хочу, чтобы страница администратора отображала ошибку рядом с полем bark_volume вместо общей ошибки, такой как сейчас. Есть ли способ указать, в каком поле выполняется проверка?

Большое спасибо заранее.

4b9b3361

Ответ 1

ОК, я понял это из этого ответа.

Вам нужно сделать что-то вроде этого:

class Dog(models.Model):
    bark_volume = models.DecimalField(...
    unladen_speed = models.DecimalField(...

    def clean_fields(self):
        if self.bark_volume < 5:
            raise ValidationError({'bark_volume': ["Must be louder!",]})

Ответ 2

class Dog(models.Model):
    bark_volume = models.DecimalField(...
    unladen_speed = models.DecimalField(...

    def clean(self):
        if self.bark_volume < 5:
            if not self._errors.has_key('bark_volume'):
                from django.forms.util import ErrorList
                self._errors['bark_volume'] = ErrorList()
            self._errors['bark_volume'].append('must be louder!')

Это работает по формам, по крайней мере. Никогда не пробовал это на самой модели, но методология должна быть одинаковой. Однако из документов Django:

Когда вы используете ModelForm, вызов is_valid() будет выполнять эти шаги проверки для всех полей, которые включены в форму. (Дополнительную информацию см. В документации ModelForm.) Вам нужно будет только вызвать метод full_clean() моделей, если вы планируете самостоятельно обрабатывать ошибки проверки, или если вы исключили поля из ModelForm, которые требуют проверки.

А...

Обратите внимание, что full_clean() не будет вызываться автоматически при вызове метода save() моделей или в результате проверки ModelForm. Вам нужно будет вызвать его вручную, если вы хотите запустить проверку модели за пределами ModelForm.

Итак, в принципе, если у вас нет действительно веских оснований для очистки полей на модели, вы должны сделать это на форме. Код для этого будет выглядеть так:

class DogForm(forms.ModelForm):

    def clean(self):
        bark_volume = self.cleaned_data.get('bark_volume')
        if bark_volume < 5:
            if not self._errors.has_key('bark_volume'):
                from django.forms.util import ErrorList
                self._errors['bark_volume'] = ErrorList()
            self._errors['bark_volume'].append('must be louder!')

        return self.cleaned_data

И это будет работать, конечно.

Ответ 3

Обратите внимание на всех, кто может столкнуться с этим с более новой версией Django - метод clean_fields из принятого ответа теперь требует параметра "исключить". Кроме того, я считаю, что в принятом ответе также отсутствует вызов его суперфункции. Последний код, который я использовал, был:

def clean_fields(self, exclude=None):
    super(Model, self).clean_fields(exclude)

    if self.field_name and not self.field_name_required:
        raise ValidationError({'field_name_required':["You selected a field, so field_name_required is required"]})

Ответ 4

Используйте метод clean_, специфичный для этого поля:

class DogForm(forms.ModelForm):
    class Meta:
        model = Dog

    def clean_bark_volume(self):
        if self.cleaned_data['bark_volume'] < 5:
            raise ValidationError("must be louder!")

См. раздел clean<fieldname> страницы Проверка формы. Кроме того, обязательно используйте cleaned_data вместо самого поля формы; последние могут иметь старые данные. Наконец, сделайте это на форме, а не на модели.

Ответ 5

Самый простой способ проверить этот конкретный случай:

from django.core.validators import MinValueValidator
from django.utils.translation import ugettext_lazy as _

class Dog(models.Model):
    bark_volume = models.DecimalField(
        ..., validators=[MinValueValidator(5, message=_("Must be louder!"))]

Документация Django о валидаторах: https://docs.djangoproject.com/en/dev/ref/validators/

Ответ 6

сокращенно, из django docs:

def clean(self):
    data = self.cleaned_data
    subject = data.get("subject")

    if subject and "help" not in subject:
        msg = "Must put 'help' in subject."
        self.add_error('subject', msg)

    return data