Почему django model.save() вызывает full_clean()?

Мне просто интересно, если кто-нибудь знает, есть ли хорошая причина, почему джанго-орм не называет "full_clean" на модели, если он не сохраняется как часть модельной формы.

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

(ПРИМЕЧАНИЕ: котировка обновлена ​​для Django 1.6... предыдущие django docs имели оговорку и о ModelForms.)

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

Я знаю, как заставить все работать правильно, я просто ищу объяснения.

Ответ 1

AFAIK, это связано с обратной совместимостью. Существуют также проблемы с ModelForms с исключенными полями, моделями со значениями по умолчанию, сигналами pre_save() и т.д.

Источники, на которые вы можете обратить внимание:

Ответ 2

Из-за совместимости, учитывая, что в ядре django функция auto clean on save не включена.

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

from django.dispatch import receiver
from django.db.models.signals import pre_save, post_save

@receiver(pre_save)
def pre_save_handler(sender, instance, *args, **kwargs):
    instance.full_clean()

Ответ 3

Самый простой способ вызова метода full_clean - это просто переопределить метод save в model:

def save(self, *args, **kwargs):
    self.full_clean()
    return super(YourModel, self).save(*args, **kwargs)

Ответ 4

Вместо вставки фрагмента кода, который объявляет получателя, мы можем использовать приложение как раздел INSTALLED_APPS в settings.py

INSTALLED_APPS = [
    # ...
    'django_fullclean',
    # your apps here,
]

Перед этим вам может потребоваться установить django-fullclean с помощью PyPI:

pip install django-fullclean

Ответ 5

Если у вас есть модель, которую вы хотите обеспечить, по крайней мере, одно отношение FK, и вы не хотите использовать null=False, потому что для этого требуется установка FK по умолчанию (который будет представлять собой данные мусора), лучший способ я Придумаем добавить пользовательские методы .clean() и .save(). .clean() вызывает ошибку проверки, а .save() вызывает чистоту. Таким образом, целостность обеспечивается как от форм, так и от другого кода вызова, командной строки и тестов. Без этого нет (AFAICT) никакого способа написать тест, который гарантирует, что модель имеет отношение FK к специально выбранной (не по умолчанию) другой модели.

class Payer(models.Model):

    name = models.CharField(blank=True, max_length=100)
    # Nullable, but will enforce FK in clean/save:
    payer_group = models.ForeignKey(PayerGroup, null=True, blank=True,)

    def clean(self):
        # Ensure every Payer is in a PayerGroup (but only via forms)
        if not self.payer_group:
            raise ValidationError(
                {'payer_group': 'Each Payer must belong to a PayerGroup.'})

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

    def __str__(self):
        return self.name