Почему django's model.save () не вызывает full_clean ()? - PullRequest
135 голосов
/ 14 декабря 2010

Мне просто любопытно, если кто-нибудь знает, есть ли веская причина, почему в django orm не вызывает 'full_clean' для модели, если она не сохраняется как часть формы модели.

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

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

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

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

Ответы [ 5 ]

53 голосов
/ 14 декабря 2010

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

Источники, которые могут вас заинтересовать:

27 голосов
/ 07 сентября 2015

Из-за совместимости автоматическая очистка при сохранении не включена в ядре django.

Если мы запускаем новый проект и хотим, чтобы метод 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()
10 голосов
/ 12 августа 2016

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

def save(self, *args, **kwargs):
    self.full_clean()
    return super(YourModel, self).save(*args, **kwargs)
1 голос
/ 12 сентября 2017

Если у вас есть модель, которую вы хотите гарантировать, чтобы она имела хотя бы одно отношение 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
0 голосов
/ 15 июня 2016

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

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

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

pip install django-fullclean
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...