es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Restricción de clave externa de Django en eliminación, incluso cuando on_delete=CASCADE.

No veo qué está mal con esto,

class Agenda(models.Model):
    ...

class AgendaResource(PolymorphicModel):
    agenda = models.ForeignKey(
        Agenda, related_name="resources", on_delete=models.CASCADE
    )
    comment = models.TextField(null=True)

class PreemptiveMeasureResource(AgendaResource):
    resource = models.ForeignKey(
        PreemptiveMeasure, on_delete=models.SET_NULL, null=True
    )
    ...

Cuando intento eliminar una agenda, es decir, Agenda.objects.get(pk=2).delete(), obtengo este problema:

update or delete on table "school_health_agendaresource" violates foreign key constraint "school_health_preemp_agendaresource_ptr_i_222e2e2c_fk_school_he" on table "school_health_preemptivemeasureresource"
DETAIL:  Key (id)=(2) is still referenced from table "school_health_preemptivemeasureresource"

¿Qué es lo que no entiendo? Supongo que tiene algo que ver con la herencia.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Sí, el problema que está encontrando se debe a la herencia de AgendaResource por PreemptiveMeasureResource. Cuando se elimina una instancia de Agenda, todas las instancias relacionadas de AgendaResource se eliminan también, incluyendo las instancias relacionadas de PreemptiveMeasureResource. Sin embargo, esas instancias tienen una relación de clave externa con PreemptiveMeasure, y eliminar las instancias de AgendaResource viola la restricción de clave externa y, por lo tanto, produce el error.

    Para resolver este problema, puede cambiar el argumento on_delete del campo ForeignKey en PreemptiveMeasureResource a models.PROTECT, lo que provocará un error de protección si hay instancias relacionadas y evitará la eliminación de la Agenda.

    Así es como puede modificar el código:

    class PreemptiveMeasureResource(AgendaResource):
        resource = models.ForeignKey(
            PreemptiveMeasure, on_delete=models.PROTECT, null=True
        )
        ...
    

    Esto garantizará que no puede eliminar una instancia de Agenda si tiene instancias relacionadas de PreemptiveMeasureResource.

Comments are closed.