Это способ проверки полей модели Django? - программирование
Подтвердить что ты не робот

Это способ проверки полей модели Django?

Как я понимаю, при создании приложения Django данные проверяются формой до того, как они вставлены в экземпляр модели, который затем записывается в базу данных. Но если я хочу создать дополнительный уровень защиты на уровне модели данных, это то, что я сделал под текущей "лучшей практикой"? Я пытаюсь гарантировать, что имя рецензента не может быть опущено или оставлено пустым. Должен ли я помещать какую-либо специальную проверку в "чистый" метод, как я здесь делал, а затем "сохранить" вызов "full_clean", который вызывает "чистый"? Если нет, то какой предпочтительный метод? Спасибо.

class Reviewer(models.Model):
    name = models.CharField(max_length=128, default=None)

    def clean(self, *args, **kwargs):
        if self.name == '':
            raise ValidationError('Reviewer name cannot be blank')
        super(Reviewer, self).clean(*args, **kwargs)

    def full_clean(self, *args, **kwargs):
        return self.clean(*args, **kwargs)

    def save(self, *args, **kwargs):
        self.full_clean()
        super(Reviewer, self).save(*args, **kwargs)
4b9b3361

Ответ 1

Во-первых, вы не должны переопределять full_clean, как вы это делали. Из django docs на full_clean:

Model.full_clean(exclude=None)
Этот метод вызывает Model.clean_fields(), Model.clean() и Model.validate_unique() в этом порядке и вызывает a ValidationError, у которого есть атрибут message_dict, содержащий ошибки со всех трех этапов.

Итак, метод full_clean уже вызывает clean, но, переопределив его, вы запретили ему вызывать другие два метода.

Во-вторых, вызов full_clean в методе save является компромиссом. Обратите внимание, что full_clean уже вызывается, когда формы модели проверяются, например. в администраторе Django. Поэтому, если вы вызываете full_clean в методе save, тогда метод будет выполняться дважды.

Как правило, для метода сохранения не рекомендуется повышать ошибку проверки, кто-то может вызвать save и не поймать полученную ошибку. Однако мне нравится, что вы вызываете full_clean, а не выполняете проверку в самом методе сохранения - этот подход позволяет модельным формам сначала поймать проблему.

Наконец, ваш метод clean будет работать, но вы действительно сможете обработать свой пример в самом поле модели. Определите свой CharField как

name = models.CharField(max_length=128)

Параметр blank по умолчанию будет False. Если поле пустое, a ValidationError будет поднято при запуске full_clean. Помещение default=None в ваш CharField не наносит никакого вреда, но это немного запутанно, если вы фактически не разрешаете None как значение.

Ответ 2

Подумав об ответах Alasdair и делая дополнительное чтение, теперь я чувствую, что модели Django не были разработаны так, чтобы их проверяли только на основе модели, как я пытаюсь сделать. Такая проверка может быть выполнена, но по себестоимости и влечет за собой использование методов валидации способами, для которых они не были предназначены.

Вместо этого теперь я считаю, что любые ограничения, отличные от тех, которые могут быть введены непосредственно в объявления полей модели (например, "unique = True" ), должны выполняться как часть проверки формы или ModelForm. Если вы хотите защитить от ввода неверных данных в базу данных проекта с помощью любых других средств (например, через ORM во время работы с интерпретатором Python), то проверка должна проводиться внутри самой базы данных. Таким образом, проверка может быть реализована на трех уровнях: 1) во-первых, реализовать все ограничения и триггеры через DDL в базе данных; 2) Внедрение любых ограничений, доступных для ваших полей модели (например, "unique = True" ); и 3) Внедрить все другие ограничения и проверки, которые отражают ваши ограничения и триггеры уровня базы данных в ваших Формах и ModelForms. При таком подходе любые ошибки проверки формы могут быть повторно отображены пользователю. И если программист напрямую взаимодействует с базой данных через ORM, он/она будет видеть исключения базы данных напрямую.

Мысли кого-нибудь?

Ответ 3

Захват сигналов предварительной записи на моих моделях гарантирует, что очистка будет вызываться автоматически.

from django.db.models.signals import pre_save

def validate_model(sender, **kwargs):
    if 'raw' in kwargs and not kwargs['raw']:
        kwargs['instance'].full_clean()

pre_save.connect(validate_model, dispatch_uid='validate_models')