En Django, on_delete es un parámetro esencial en campos de relación como ForeignKey, OneToOneField y ManyToManyField.
Determina cómo manejar los registros dependientes cuando se elimina un objeto relacionado, garantizando la integridad de los datos y evitando registros huérfanos.
A continuación, se muestra como un Sistema de Gestión de Aprendizaje (LMS), exploramos el uso del atributo on_delete al definir relaciones entre modelos:
from django.db import models
class Estudiante(models.Model):
nombre = models.CharField(max_length=255)
class Tarea(models.Model):
titulo = models.CharField(max_length=255)
estudiante = models.ForeignKey(Estudiante, on_delete=models.CASCADE) models.CASCADE: Elimina también los objetos relacionados.models.PROTECT: Evita que se elimine el objeto relacionado si hay dependencias.models.SET_NULL: Establece el campo relacionado como NULL (requiere que el campo permita valores nulos).models.SET_DEFAULT: Asigna un valor por defecto al campo relacionado.models.DO_NOTHING: No hace nada, lo que puede provocar errores si hay restricciones de clave foránea en la base de datos.La eliminación en cascada asegura que, cuando un objeto principal es eliminado, todos los objetos relacionados que dependen de él también sean eliminados automáticamente. Esto ayuda a mantener la integridad referencial en la base de datos y evita datos huérfanos.
class Tarea(models.Model):
estudiante = models.ForeignKey(Estudiante, on_delete=models.CASCADE)
# Al eliminar un estudiante, también se eliminan todas sus tareas
estudiante = Estudiante.objects.get(nombre="María")
estudiante.delete() # Esto eliminará todas las tareas de María La opción PROTECT previene la eliminación de un objeto referenciado.
Si se intenta eliminar dicho objeto, se generará un error ProtectedError, garantizando que los objetos dependientes no se vean afectados accidentalmente.
class Tarea(models.Model):
estudiante = models.ForeignKey(Estudiante, on_delete=models.PROTECT)
# Intentar eliminar un estudiante con tareas generará un error
try:
estudiante.delete()
except ProtectedError:
print("No se puede eliminar un estudiante con tareas existentes") RESTRICT funciona de manera similar a PROTECT, pero con una diferencia clave: permite la eliminación de un objeto referenciado solo si forma parte de una operación en cascada.
De lo contrario, se bloquea la eliminación para evitar la pérdida de datos relacionados.
class Curso(models.Model):
estudiantes = models.ManyToManyField(Estudiante)
class Tarea(models.Model):
estudiante = models.ForeignKey(Estudiante, on_delete=models.RESTRICT) SET_NULL establece la clave foránea de los objetos relacionados en NULL cuando se elimina el objeto referenciado.
Esto asegura que las relaciones no se rompan, pero los objetos dependientes ya no estarán vinculados al objeto eliminado.
class Tarea(models.Model):
estudiante = models.ForeignKey(
Estudiante,
on_delete=models.SET_NULL,
null=True
)
# Al eliminar un estudiante, el campo estudiante de tarea se convierte en NULL
estudiante.delete() SET_DEFAULT asigna un valor predeterminado predefinido a la clave foránea cuando se elimina el objeto referenciado.
Esta opción garantiza que las relaciones se mantengan, pero con un valor por defecto en lugar del objeto eliminado.
class Tarea(models.Model):
estudiante = models.ForeignKey(
Estudiante,
on_delete=models.SET_DEFAULT,
default=1 # ID de estudiante predeterminado
)
# Eliminar un estudiante establece el estudiante de tarea en el predeterminado
estudiante.delete() SET() permite definir dinámicamente el nuevo valor de la clave foránea al eliminar el objeto referenciado, mediante la ejecución de una función personalizada.
Esto brinda flexibilidad para actualizar las referencias de manera específica según las necesidades del sistema.
def obtener_estudiante_predeterminado():
return Estudiante.objects.first()
class Tarea(models.Model):
estudiante = models.ForeignKey(
Estudiante,
on_delete=models.SET(obtener_estudiante_predeterminado)
)
# Elimina el estudiante y establece la tarea en un estudiante seleccionado dinámicamente
estudiante.delete() DO_NOTHING no realiza ninguna acción automática cuando se elimina el objeto referenciado.
Las relaciones permanecen intactas y el sistema no modifica los objetos relacionados, lo que puede ser útil en escenarios donde se desea manejar las referencias manualmente.
class Tarea(models.Model):
estudiante = models.ForeignKey(
Estudiante,
on_delete=models.DO_NOTHING
)
# Elimina el estudiante sin modificar la tarea (usar con precaución)
estudiante.delete() La opción on_delete es una herramienta poderosa en Django para gestionar relaciones entre modelos.
Comprendiendo y aplicando estas estrategias, puede crear esquemas de base de datos robustos y mantenibles que manejen las relaciones de datos con precisión y cuidado.