Each Answer to this Q is separated by one/two green lines.
I’m using Django to create a stock photo site, I have an ImageField in my model, the problem is that when the user updates the image field, the original image file isn’t deleted from the hard disk.
How can I delete the old images after an update?
pip install django-cleanup
INSTALLED_APPS = ( ... 'django_cleanup.apps.CleanupConfig', # should be placed after your apps )
You’ll have to delete the old image manually.
The absolute path to the image is stored in
your_image_field.path. So you’d do something like:
But, as a convenience, you can use the associated FieldFile object, which gives easy access to the underlying file, as well as providing a few convenience methods. See http://docs.djangoproject.com/en/dev/ref/models/fields/#filefield-and-fieldfile
Use this custom save method in your model:
def save(self, *args, **kwargs): try: this = MyModelName.objects.get(id=self.id) if this.MyImageFieldName != self.MyImageFieldName: this.MyImageFieldName.delete() except: pass super(MyModelName, self).save(*args, **kwargs)
It works for me on my site. This problem was bothering me as well and I didn’t want to make a cleanup script instead over good bookkeeping in the first place. Let me know if there are any problems with it.
Before updating the model instance, you can use the delete method of
FileField object. For example, if the
ImageField is named as
photo and your model instance is
profile, then the following will remove the file from disk
For more clarification, here is the django doc
You can define
pre_save reciever in models:
@receiver(models.signals.pre_save, sender=UserAccount) def delete_file_on_change_extension(sender, instance, **kwargs): if instance.pk: try: old_avatar = UserAccount.objects.get(pk=instance.pk).avatar except UserAccount.DoesNotExist: return else: new_avatar = instance.avatar if old_avatar and old_avatar.url != new_avatar.url: old_avatar.delete(save=False)
My avatrs has unique url for each person like “avatars/ceb47779-8833-4719-8711-6f4e5cabb2b2.png”. If user upload new image with different extension like jpg, delete_file_on_change_extension reciever remove old image, before save new with url “avatars/ceb47779-8833-4719-8711-6f4e5cabb2b2.jpg” (in this case). If user uploads new image with same extension django overwrite old image on storage (disk), because images paths are the same.
This works fine with AWS S3 django-storage.
Here is an app that deletes orphan files by default: django-smartfields.
It will remove files whenever:
- field value was replaced with a new one (either uploaded or set manually)
- field is cleared through the form (in case that field is not required, of course)
- the model instance itself containing the field is deleted.
It is possible to turn that cleanup feature off using an argument:
ImageField(keep_orphans=True) on per field basis, or globally in settings
SMARTFIELDS_KEEP_ORPHANS = True.
from django.db import models from smartfields import fields class MyModel(models.Model): image = fields.ImageField() document = fields.FileField()
try this, it will work even if old file is deleted
def logo_file(instance, filename): try: this = business.objects.get(id=instance.id) if this.logo is not None: path = "%s" % (this.logo) os.remove(path) finally: pass..
code will work even without “try .. finally” but it will generate problem if file was accidently deleted.
changed: move model matching inside “try” so it will not throw any error at user signup
Let me know if there are any problems.
Completing Chris Lawlor’s answer, tried this and works.
from YOURAPP.settings import BASE_DIR try: os.remove(BASE_DIR + user.userprofile.avatarURL) except Exception as e: pass
The URL has a pattern of
What I did is saving the path to the old image and if form is valid I would delete the old one.
if request.method == 'POST': old_image = "" if request.user.profile.profile_picture: old_image = request.user.profile.profile_picture.path form = UpdateProfileForm(request.POST,request.FILES,instance = profile) if form.is_valid(): if os.path.exists(old_image): os.remove(old_image) form.save()
It is a little messy , but you do not install third parties or anythin