python - queryset - ¿Es esta la forma de validar los campos del modelo Django?
python django documentation (3)
Al capturar las señales de pre-guardado en mis modelos, se garantiza que la limpieza se llamará automáticamente.
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'')
Como lo entiendo, cuando uno crea una aplicación Django, los datos son validados por el formulario antes de insertarlo en una instancia del modelo que luego se escribe en la base de datos. Pero si quiero crear una capa adicional de protección en la capa del modelo de datos, ¿es lo que he hecho por debajo de la "mejor práctica actual"? Estoy tratando de asegurar que el nombre de un crítico no pueda omitirse ni dejarse en blanco. ¿Debería poner una validación personalizada en el método ''limpio'' como lo he hecho aquí y luego tener ''guardar'' llamada ''full_clean "que llama'' limpiar ''? Si no, ¿cuál es el método preferido? Gracias.
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)
Después de pensar en la respuesta de Alasdair y hacer una lectura adicional, ahora tengo la sensación de que los modelos de Django no se diseñaron para validarse de forma exclusiva como lo estoy intentando hacer. Dicha validación se puede hacer, pero a un costo, y conlleva el uso de métodos de validación en formas en las que no estaban destinados.
En cambio, ahora creo que cualquier otra restricción que no sea la que se puede ingresar directamente en las declaraciones del campo del modelo (por ejemplo, "único = Verdadero") se debe realizar como parte de la validación de Form o ModelForm. Si uno quiere protegerse contra la introducción de datos no válidos en la base de datos de un proyecto a través de cualquier otro medio (por ejemplo, a través del ORM mientras trabaja con el intérprete de Python), la validación debe realizarse dentro de la propia base de datos. Por lo tanto, la validación podría implementarse en tres niveles: 1) Primero, implementar todas las restricciones y activadores a través de DDL en la base de datos; 2) Implemente cualquier restricción disponible para los campos de su modelo (por ejemplo, "único = Verdadero"); y 3) Implemente todas las demás restricciones y validaciones que reflejen las restricciones y los desencadenantes a nivel de base de datos dentro de sus Formularios y ModelForms. Con este enfoque, cualquier error de validación de formulario se puede volver a mostrar al usuario. Y si el programador está interactuando directamente con la base de datos a través del ORM, él / ella vería las excepciones de la base de datos directamente.
¿Pensamientos a alguien?
En primer lugar, no debe anular full_clean
como lo ha hecho. De los documentos de django en full_clean :
Model.full_clean(exclude=None)
Este método llama aModel.clean_fields()
,Model.clean()
yModel.validate_unique()
, en ese orden y genera unValidationError
que tiene un atributomessage_dict
contiene errores de las tres etapas.
Así que el método full_clean
ya llama clean
, pero al anularlo, evitó que llamara a los otros dos métodos.
En segundo lugar, llamar a full_clean
en el método de save
es una compensación. Tenga en cuenta que ya se llama a full_clean
cuando se validan los formularios modelo, por ejemplo, en el administrador de Django. Así que si llama a full_clean
en el método de save
, entonces el método se ejecutará dos veces.
Generalmente no se espera que el método de guardar genere un error de validación, alguien podría llamar save
y no capturar el error resultante. Sin embargo, me gusta que llame a full_clean
lugar de hacer la comprobación del método de guardado en sí mismo; este enfoque permite que los formularios modelo full_clean
el problema primero.
Finalmente, su método de clean
funcionaría, pero en realidad puede manejar su caso de ejemplo en el mismo campo del modelo. Define tu campo de CharField
como
name = models.CharField(max_length=128)
La opción en blank
defecto será Falso. Si el campo está en blanco, se generará un full_clean
ValidationError
cuando ejecute full_clean
. Poner default=None
en tu CharField
no hace ningún daño, pero es un poco confuso cuando en realidad no permites None
como valor.