Django - Как указать, в каком поле проверки не удается? - PullRequest
51 голосов
/ 13 июня 2011

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

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 вместо общей ошибки, как сейчас.Есть ли способ указать, в каком поле проверки не выполняется?

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

Ответы [ 6 ]

96 голосов
/ 14 июня 2011

Хорошо, я понял это из этого ответа .

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

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!",]})
12 голосов
/ 13 июня 2011
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

И это точно сработает.

7 голосов
/ 04 апреля 2014

Чтобы заметить любого, кто может столкнуться с этим с более новой версией 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"]})
6 голосов
/ 13 июня 2011

Используйте метод 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 вместо самого поля формы; последний может иметь старые данные. Наконец, сделайте это на форме, а не на модели.

4 голосов
/ 06 августа 2012

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

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!"))]

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

2 голосов
/ 22 ноября 2017

сокращенно от 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
...