Pregunta

El uso de los siguientes modelos relacionados (una entrada de blog puede tener múltiples revisiones):

class BlogEntryRevision(models.Model):
    revisionNumber = models.IntegerField()
    title = models.CharField(max_length = 120)
    text = models.TextField()
    [...]

class BlogEntry(models.Model):
    revisions = models.ManyToManyField(BlogEntryRevision)
    [...]

¿Cómo puedo decirle a Django para eliminar todos los BlogEntryRevisions relacionados cuando se elimina el BlogEntry correspondiente? El valor por defecto parece ser la de mantener los objetos en una relación de muchos a muchos, si se elimina un objeto del "otro" lado. Cualquier manera de hacer esto? - preferiblemente sin anulando BlogEntry.delete

¿Fue útil?

Solución

creo que está malinterpretando la naturaleza de una relación ManyToMany. Se habla de "la entrada de blog correspondiente" se va a eliminar. Pero el punto central de un ManyToMany es que cada BlogEntryRevision tiene múltiples BlogEntries relacionados con ella. (Y, por supuesto, cada uno tiene múltiples BlogEntry BlogEntryRevisions, pero ya se sabe que ya.)

A partir de los nombres que ha usado, y el hecho de que desea que esta funcionalidad eliminación en cascada, creo que sería mejor con un estándar de ForeignKey BlogEntryRevision a BlogEntry. Mientras no se establece null=True en ese ForeignKey, supresiones en cascada -. Cuando se elimina la entrada de blog, todas las revisiones serán demasiado

A partir de Django 2.0

El ForeignKey inicializador ahora requiere que se especifique el parámetro on_delete:

from django.db import models
from .models import MyRelatedModel


class model(models.Model):
    related_model = models.ForeignKey(MyRelatedModel, on_delete=models.CASCADE)

Otros consejos

Tenía este caso de uso exacto de hoy:

  • Modelo Autor: puede tener varias entradas
  • Modelo Fecha de entrada: puede tener varios autores

Para esto, estoy usando un ManyToManyRelationship.

Mi caso de uso fue: si elimino la última entrada de un autor en particular, entonces este autor debe suprimirse también.

La solución se puede lograr utilizando la pre_delete señal :

@receiver(pre_delete, sender=Entry)
def pre_delete_story(sender, instance, **kwargs):
    for author in instance.authors.all():
        if author.entries.count() == 1 and instance in author.entries.all():
            # instance is the only Entry authored by this Author, so delete it
            author.delete()

Se puede utilizar un modelo personalizado gerente , pero la documentación parece indicar que hace algo como esto ya y no puedo recordar exactamente lo que esto significa:

  

El método de eliminación, convenientemente, es   llamado delete (). Este método   elimina inmediatamente el objeto y tiene   valor de retorno. Ejemplo:

e.delete()
     

También puede eliminar objetos   al por mayor. Cada QuerySet tiene un delete ()   método, que elimina todos los miembros de   que QuerySet.

     

Por ejemplo, esto elimina todas las entradas   los objetos con un año pub_date de 2005:

Entry.objects.filter(pub_date__year=2005).delete()
     

Tenga en cuenta que esta voluntad, siempre que sea   posible, ser ejecutado puramente en SQL,   y por lo que el delete () de   instancias de objetos individuales no se   necesariamente ser llamado durante el   proceso. Si usted ha proporcionado una costumbre   eliminar () método en una clase de modelo y   querrá asegurarse de que se le llama, se   tendrá que "manualmente" eliminar   instancias de dicho modelo (por ejemplo, por   iterar sobre un QuerySet y llamadas   delete () en cada objeto individual)   en lugar de utilizar la mayor delete ()   método de un QuerySet.

     

Cuando Django borra un objeto,   emula el comportamiento del SQL   restricción ON DELETE CASCADE - en   Es decir, cualquier objeto que tenían   claves externas apuntando hacia el objeto a   suprimirse serán borrados junto con   . It Por ejemplo:

b = Blog.objects.get(pk=1)
# This will delete the Blog and all of its Entry objects.
b.delete()

Simplemente utilice el clear() método para eliminar los objetos relacionados desde Django usa el pase modelo para especificar las relaciones que el método claro elimina todos los BlogEntryRevision relacionado

be = BlogEntry.objects.get(id=1)
be.blogentryrevision_set.clear()
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top