0

My model File has as main purpose to link multiple files for one Invoice.

class File(models.Model):
    invoice = models.ForeignKey(Invoice, related_name = 'files', on_delete = models.CASCADE)
    file = models.FileField(upload_to = 'storage/invoicing/')
    
    def delete(self, *args, **kwargs):
        self.file.delete()
        return super(File, self).delete(*args, **kwargs)

When i delete one instance of my model File, the file stored in storage/invoicing is also deleted because of my modified delete() method.

However, if i delete the instance from the parent model Invoice, the file is not deleted. Even with the File instance being removed from the database, the file is still acessable.

How can i code the parent model to delete everything from the children model, including the files?

I've searched a bit and i know that probably signals like post_delete can help me here, but i really don't know how to code it.

Ricardo Vilaça
  • 846
  • 1
  • 7
  • 18
  • 1
    check this question's answers https://stackoverflow.com/questions/16041232/django-delete-filefield – ishak O. Dec 06 '20 at 21:06
  • @ishakO. I tried signals and the file is still accessible. The `Invoice` gets deleted but the file is still on the server. I'm using an aws s3 bucket for storage, i don't know if that changes anything btw – Ricardo Vilaça Dec 06 '20 at 21:39

1 Answers1

0

pre_delete signal can help you to solve the problem.

your_app/signals.py

from django.db.models.signals import pre_delete

from your_app.models import Invoice


def remove_files(instance, **kwargs):
    for file_obj in instance.files.all():
        file_obj.file.delete()


pre_delete.connect(remove_files, sender=Invoice)

IMPORTANT!

As you might have guessed, pre_delete signal calls the specified function before deleting the object(in this case instance of Invoice class). It means that before removing the invoice and all related file objects(because of CASCADE), it will delete all files associated with the file objects that refer to the invoice. If for some reason deletion won't happen you'll lose files anyway.

Davit Tovmasyan
  • 3,238
  • 2
  • 20
  • 36
  • thanks, but that doesn't work for me. I just copied the code you gave me and the `Invoice` gets deleted, but the `file` is still accessible if i keep the url of the file storage. I forgot to mention but, the `file` storage is located in a aws s3 bucket. I'm not sure if that changes anything – Ricardo Vilaça Dec 06 '20 at 21:38
  • Btw, i think you have a typo. `invoice.files.all()` should be `instance.files.all()` right? Anyway, i tried both ways and no success still – Ricardo Vilaça Dec 06 '20 at 21:42
  • Yes it should be instance.files.all(). – Davit Tovmasyan Dec 06 '20 at 22:15