personalizados - ¿Forma correcta de validar los objetos modelo de Django?
guardar datos de un formulario django (1)
Tuve un malentendido similar sobre el ORM cuando comencé con Django.
1) No, no pongas self.full_clean()
dentro de save
. Ya sea
A) use un ModelForm
(que causará la misma validación) Nota: ModelForm.is_valid()
no llamará a Model.full_clean
explícitamente, pero realizará exactamente las mismas comprobaciones que Model.full_clean
. Ejemplo:
class PersonForm(forms.ModelForm):
class Meta:
model = Person
def add_person(request):
if request.method == ''POST'':
form = PersonForm(request.POST, request.FILES)
if form.is_valid(): # Performs your validation, including ``validate_gender``
person = form.save()
return redirect(''some-other-view'')
else:
form = PersonForm()
# ... return response with ``form`` in the context for rendering in a template
También tenga en cuenta que los formularios no se pueden usar solo en vistas que los traducen en plantillas: son geniales para cualquier tipo de uso, incluida una API, etc. Después de ejecutar form.is_valid()
y obtener errores, tendrá form.errors
que es un diccionario que contiene todos los errores del formulario, incluida una clave llamada ''__all__''
que contendrá errores que no sean de campo.
B) Simplemente use model_instance.full_clean()
en su vista (u otra capa de aplicación lógica), en lugar de usar un formulario, pero las formas son una buena abstracción para esto.
2) Realmente no tengo una solución, pero nunca me he encontrado con un problema así, incluso en proyectos grandes (el proyecto actual con el que trabajo con mi compañía tiene 146 tablas) y no sospecho que sea una preocupación en su caso tampoco.
Todavía estoy tratando de comprender la forma correcta de validar un objeto modelo Django utilizando un validador personalizado en el nivel del modelo. Sé que la validación generalmente se realiza en forma de formulario o modelo. Sin embargo, quiero asegurar la integridad de mis datos en el nivel del modelo si estoy interactuando con él a través del ORM en el shell de Python. Aquí está mi enfoque actual:
from django.db import models
from django.core import validators
from django.core exceptions import ValidationError
def validate_gender(value):
""" Custom validator """
if not value in (''m'', ''f'', ''M'', ''F''):
raise ValidationError(u''%s is not a valid value for gender.'' % value)
class Person(models.Model):
name = models.CharField(max_length=128)
age = models.IntegerField()
gender = models.CharField(maxlength=1, validators=[validate_gender])
def save(self, *args, **kwargs):
""" Override Person''s save """
self.full_clean(exclude=None)
super(Person, self).save(*args, **kwargs)
Aquí están mis preguntas:
¿Debo crear una función de validación personalizada, designarla como un validador y luego anular la función de guardar () de la persona como he hecho anteriormente? (Por cierto, sé que podría validar mis elecciones de género usando la opción de campo ''elecciones'', pero creé ''validate_gender'' con el propósito de ilustración).
Si realmente quiero asegurar la integridad de mis datos, ¿no debería escribir pruebas de unidades de Django para probarlas en la capa de modelo, sino también pruebas equivalentes de unidad de nivel de base de datos usando Python / Psycopg? Me he dado cuenta de que las pruebas unitarias de Django, que plantean ValidationErrors, solo prueban la comprensión del modelo del esquema de la base de datos utilizando una copia de la base de datos. Incluso si tuviera que usar South para migraciones, cualquier restricción a nivel de base de datos está limitada a lo que Django puede entender y traducir en una restricción de Postgres. Si necesito una restricción personalizada que Django no pueda replicar, podría ingresar datos en mi base de datos que violen esa restricción si estoy interactuando con la base de datos directamente a través del terminal psql.
¡Gracias!