¿Por qué django’s model.save () llama a full_clean ()?

Solo tengo curiosidad si alguien sabe si hay una buena razón por la que el orm de django no llama ‘full_clean’ en un modelo a menos que se guarde como parte de un formulario modelo.

Tenga en cuenta que no se llamará automáticamente a full_clean () cuando llame al método save () de su modelo. Deberá llamarlo manualmente cuando desee ejecutar la validación de modelo de un solo paso para sus propios modelos creados manualmente. documento limpio completo de django

(NOTA: cotización actualizada para Django 1.6 … los documentos anteriores de Django también tenían una advertencia sobre ModelForms).

¿Hay buenas razones para que la gente no quiera este comportamiento? Pensaría que si se tomara el tiempo de agregar validación a un modelo, querría que esa validación se ejecute cada vez que se guarda el modelo.

Sé cómo hacer que todo funcione correctamente, solo estoy buscando una explicación.

AFAIK, esto es debido a la compatibilidad hacia atrás. También hay problemas con ModelForms con campos excluidos, modelos con valores predeterminados, señales de pre_save (), etc.

Fuentes en las que podría estar interesado:

Debido a la compatibilidad considerando, la limpieza automática al guardar no está habilitada en el kernel django.

Si estamos comenzando un nuevo proyecto y queremos que el método de save predeterminado en el Modelo se pueda limpiar automáticamente, podemos usar la siguiente señal para limpiar antes de que se guarde cada modelo.

 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() 

La forma más sencilla de llamar al método full_clean es anular el método de save en su model :

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

Si tiene un modelo que quiere asegurarse tiene al menos una relación FK, y no quiere usar null=False porque eso requiere establecer un FK predeterminado (que sería información basura), de la mejor manera he venido con es agregar .clean() personalizados .clean() y .save() . .clean() genera el error de validación y .save() llama a limpiar. De esta manera, la integridad se aplica tanto desde los formularios como desde otro código de llamada, la línea de comandos y las pruebas. Sin esto, no hay (AFAICT) ninguna forma de escribir una prueba que garantice que un modelo tenga una relación FK con un modelo específicamente elegido (no predeterminado).

 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 

En lugar de insertar un fragmento de código que declara un receptor, podemos usar una aplicación como sección INSTALLED_APPS en settings.py

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

Antes de eso, es posible que necesites instalar django-fullclean usando PyPI:

 pip install django-fullclean