# deleting a file using post\_delete

**URL:** <https://forum.djangoproject.com/t/deleting-a-file-using-post-delete/26092>\
**Category:** Using the ORM\
**Created:** [December 12, 2023, 7:11am UTC](https://forum.djangoproject.com/t/deleting-a-file-using-post-delete/26092 "2023-12-12T07:11:43Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![xtlc](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/xtlc/32/3887_2.png) [@xtlc](https://forum.djangoproject.com/u/xtlc)\
**Post date:** [December 12, 2023, 7:11am UTC](https://forum.djangoproject.com/t/deleting-a-file-using-post-delete/26092/1 "2023-12-12T07:11:43Z")

</div>

I tried to make sure a resource is deleted, when the corresponding instance is deleted:

my model:

```auto
class SomeField(models.Model):
    name = models.CharField("name", max_length = 32, unique = True)
    
class SomeResource(models.Model):
    somefield = models.ForeignKey(SomeField, on_delete = models.CASCADE)
    file = models.FileField("the file", max_length = 255)

```

first approach:

```auto
def file_cleanup(sender, **kwargs):
    if Path(kwargs["instance"].file.path).is_file():
        kwargs["instance"].file.delete()

```

signal:

```auto
post_delete.connect(file_cleanup, sender=SomeResource, dispatch_uid="someresource.file_cleanup")

```

But in the database I see the instance is never deleted. The file is correctly removed. If I comment out the `kwargs["instance"].file.delete()` line, the instance is correctly removed. Why?

my workaround:

```auto
def file_cleanup(sender, **kwargs):
    path = Path(kwargs["instance"].file.path)
    if path.is_file():
        path.unlink()

```

I am trying to understand why the first “solution” did not work.

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [December 12, 2023, 1:28pm UTC](https://forum.djangoproject.com/t/deleting-a-file-using-post-delete/26092/2 "2023-12-12T13:28:10Z")

</div>

What happens if you change this from a `post_delete` sitgnal to a `pre_delete` signal?

From the docs for the `post_delete` signal:

> `instance`
> 
> The actual instance being deleted.
> 
> Note that the object will no longer be in the database, so be very careful what you do with this instance.

(Note: I have no actual idea what is happening here, or what the effects may be of what you’re doing - I learned a long time ago to avoid signals except in those cases where they’re actually _needed_, and so I’ve never encountered anything like this.)

---

<div class="post-metadata">

**Author:** ![antoinehumbert](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/antoinehumbert/32/14851_2.png) [@antoinehumbert](https://forum.djangoproject.com/u/antoinehumbert)\
**Post date:** [December 13, 2023, 8:53pm UTC](https://forum.djangoproject.com/t/deleting-a-file-using-post-delete/26092/3 "2023-12-13T20:53:22Z")

</div>

The `delete` method (you are calling) on `FieldFile` accepts a `save` parameter which defaults to `True`. So, in your example, the model object is saved after deleting file, thus recreating the object in database. If you pass `save=False` parameter when calling `delete`, the model object should not be recreated in database.

---

<div class="post-metadata">

**Author:** ![antoinehumbert](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/antoinehumbert/32/14851_2.png) [@antoinehumbert](https://forum.djangoproject.com/u/antoinehumbert)\
**Post date:** [December 13, 2023, 9:01pm UTC](https://forum.djangoproject.com/t/deleting-a-file-using-post-delete/26092/4 "2023-12-13T21:01:55Z")

</div>

Side note: when checking for existence of file, using

> [@xtlc](#):
>
> `Path(kwargs["instance"].file.path).is_file()`

you suppose the storage backend is a `FileSystemStorage`.

If you want your code to be agnostic from backend storage (for example if you change it to `S3Storage` from `django-storages`) and still want to have your cleaning function working for such backend, you could use following test :

```auto
if kwargs["instance"].file.storage.exists(kwargs["instance"].file.name):

```

---

<div class="post-metadata">

**Author:** ![xtlc](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/xtlc/32/3887_2.png) [@xtlc](https://forum.djangoproject.com/u/xtlc)\
**Post date:** [December 14, 2023, 8:22pm UTC](https://forum.djangoproject.com/t/deleting-a-file-using-post-delete/26092/5 "2023-12-14T20:22:21Z")

</div>

When trying your suggestion I end up with

```auto
TypeError file_cleanup() missing 1 required positional argument: 'sender'

```

```auto
def file_cleanup(sender, **kwargs):
    from .models import NewLayoutResource
    if isinstance(sender, NewLayoutResource):
        if kwargs["instance"].file.storage.exists(kwargs["instance"].file.name):
            kwargs["instance"].file.delete(save = False)

```

I thought using signals was smart, but after reading @KenWhitesell 's post I decided to go for:

```auto
class SomeResource(models.Model):
    somefield = models.ForeignKey(SomeField, on_delete = models.CASCADE)
    file = models.FileField("the file", max_length = 255)

    def delete_file(self):
        if (p := Path(self.file.path)).is_file():
            p.unlink()

```

and in the `clean` method of my `SomeResourceForm`:

```auto
def clean(self):
    clean_data = super().clean()
    if (self.has_changed() and "file" in self.initial.keys()) or clean_data["DELETE"] == True:
        self.instance.delete_file()
        return clean_data

```

which also works just fine and avoids all signals 🙂 I would probably need some time to wrap my head around pre/post\_delete signals ☹
