Search code examples
wagtailwagtail-admin

How to automaticaly delete images linked to a page after deleting the page?


I have an Annonce page with this model:

class AnnoncePage(Page):
    date = models.DateField("Date de publication", blank=True, null=True)
    description = RichTextField(features=['h2', 'h3', 'bold', 'italic', 'link', 'hr', 'ol', 'ul'], blank=True)
    lieu = models.CharField(blank=True, max_length=200)
    surface = models.PositiveSmallIntegerField(blank=True, null=True)
    nb_pieces = models.PositiveSmallIntegerField(blank=True, null=True)
    prix_affiché_index = models.CharField(blank=True, max_length=200, null=True)
    conditions_vente_et_prix = RichTextField(blank=True, features=['h2', 'h3', 'bold', 'italic', 'link', 'hr', 'ol', 'ul'])

    def main_image(self):
        gallery_item = self.gallery_images.first()
        if gallery_item:
            return gallery_item.image
        else:
            return None

    content_panels = Page.content_panels + [
        FieldPanel('date'),
        InlinePanel('gallery_images', label="Gallery images"),
        FieldPanel('lieu', classname="full"),
        FieldPanel('surface', classname="full"),
        FieldPanel('nb_pieces', classname="full"),
        FieldPanel('description', classname="full"),
        FieldPanel('prix_affiché_index', classname="full"),
        FieldPanel('conditions_vente_et_prix', classname="full")
    ]

    promote_panels = []
    settings_panels = []

    max_count = 20

class AnnoncePageGalleryImage(Orderable):
    page = ParentalKey(AnnoncePage, on_delete=models.SET_NULL, related_name='gallery_images', null=True)
    image = models.ForeignKey(
        'wagtailimages.Image', on_delete=models.SET_NULL, related_name='+', null=True
    )

    panels = [
        ImageChooserPanel('image')
    ]

How can I automaticaly delete the images of the Annonce page after deleting the Annonce page itself ? Do I need to change the model ?


Solution

  • The Wagtail image object can be used in other places. Deleting those automagically might have nasty side effects for other content.

    You can add a delete method to AnnoncePage or use a pre_delete signal. You need to iterate over all related gallery images and delete the related Wagtail images. Django leaves the file on disk, so you might want to handle that too.

    class AnnoncePage(Page):
        ...
        def delete(self):
             for gallery_image in self.gallery_images.all():
                  # Delete the file on disk here ...
                  # After, delete the db obj.
                  gallery_image.image.all().delete()
             self.gallery_images.all().delete()
             super().delete()
    

    Disclaimer: untested code.

    https://docs.djangoproject.com/en/dev/topics/db/models/#overriding-model-methods https://docs.djangoproject.com/en/dev/ref/signals/#pre-delete https://docs.djangoproject.com/en/3.1/ref/models/fields/#django.db.models.fields.files.FieldFile.delete

    Note that the delete method and pre_delete signal are not called on bulk actions. Your milage may vary.