Saltar al contenido

Anule el método de eliminación del modelo de Django para la eliminación masiva

Luego de consultar especialistas en el tema, programadores de deferentes ramas y profesores hemos dado con la respuesta al problema y la compartimos en esta publicación.

Solución:

Lo hace:

El método delete() realiza una eliminación masiva y no llama a ningún método delete() en sus modelos. Sin embargo, emite las señales pre_delete y post_delete para todos los objetos eliminados (incluidas las eliminaciones en cascada).

Para que eso funcione, puede anular el método de eliminación en QuerySet, y luego aplicar eso QuerySet como gerente:

class ImageQuerySet(models.QuerySet):

    def delete(self, *args, **kwargs):
        for obj in self:
            obj.img.delete()
        super(ImageQuerySet, self).delete(*args, **kwargs)

class Image(models.Model):
    objects = ImageQuerySet.as_manager()
    img = models.ImageField(upload_to=get_image_path)
    ...
    def delete(self, *args, **kwargs):
        self.img.delete()
        super(Image, self).delete(*args, **kwargs)

El método de eliminación de queryset funciona directamente en la base de datos. no llama Model.delete() métodos. De los documentos:

Tenga en cuenta que, siempre que sea posible, esto se ejecutará exclusivamente en SQL, por lo que los métodos delete() de instancias de objetos individuales no se llamarán necesariamente durante el proceso. Si proporcionó un método delete() personalizado en una clase de modelo y desea asegurarse de que se llame, deberá eliminar “manualmente” las instancias de ese modelo (por ejemplo, iterando sobre un QuerySet y llamando a delete() en cada objeto individualmente) en lugar de usar el método de eliminación masiva () de un QuerySet.

Si desea anular el comportamiento predeterminado de la interfaz de administración de Django, puede escribir un delete acción:

https://docs.djangoproject.com/en/1.7/ref/contrib/admin/actions/

Otro método es anular post_delete (o pre_delete) señal en lugar de delete método:

https://docs.djangoproject.com/en/1.7/ref/signals/#django.db.models.signals.post_delete

Como pre_delete, pero enviado al final del método delete() de un modelo y el método delete() de un conjunto de consultas.

Creo que este problema se aborda en los documentos.

En donde dice:

Los métodos de modelo anulados no se llaman en operaciones masivas

Tenga en cuenta que el método delete() para un objeto no se llama necesariamente cuando se eliminan objetos de forma masiva mediante un QuerySet o como resultado de una eliminación en cascada. Para garantizar que se ejecute la lógica de eliminación personalizada, puede usar señales pre_delete y/o post_delete.

Desafortunadamente, no hay una solución cuando se crean o actualizan objetos en masa, ya que no se llama a save(), pre_save y post_save.

Como se sugiere en los documentos anteriores, creo que una mejor solución es usar el post_delete señal, así:

from django.db.models.signals import post_delete
from django.dispatch import receiver

class Image(models.Model):
    img = models.ImageField(upload_to=get_image_path)
    ...

@receiver(post_delete, sender=Image)
def delete_image_hook(sender, instance, using, **kwargs):
    instance.img.delete()

A diferencia de anular el delete método, el delete_image_hook La función debe llamarse también en eliminaciones masivas y eliminaciones en cascada. Aquí hay más información sobre el uso de las señales de Django: https://docs.djangoproject.com/en/1.11/topics/signals/#connecting-to-signals-sent-by-specific-senders

Nota sobre las respuestas anteriores:
Algunas de las publicaciones anteriores sugieren anular el delete método de QuerySet, que puede tener implicaciones en el rendimiento y otros comportamientos no deseados. Quizás esas respuestas se escribieron antes de que se implementaran las Señales de Django, pero creo que usar Señales es un enfoque más limpio.

Reseñas y puntuaciones

Si piensas que ha sido de provecho nuestro artículo, sería de mucha ayuda si lo compartes con más entusiastas de la programación así nos ayudas a extender esta información.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *