I have a user profile model with optional avatar that looks like
#models.py
class UserProfile(models.Model):
avatar = models.ImageField(upload_to=avatars null=True, blank=True)
.
.
.
Then a form like:
#forms.py
class UserProfileForm(forms.ModelForm):
avatar = forms.ImageField(required=False,....)
class Meta:
model = UserProfile
Finally, a view including
#views.py
def edit_profile(....)
profile_obj = request.user.userprofile
form = UserProfile(data=request.POST, files=request.FILES, instance=profile_obj)
if form.is_valid():
form.save()
Now when the template for editing the user's profile, and avatar, is rendered, it included a Clear
checkbox, which when selected let's the user remove their avatar photo. It leaves myuser.avatar
in the state <ImageFieldFile: None>
, however it does not delete the file in the storage area of the site itself (i.e. the jpg,png or whatever). I've read that this is by design in Django 1.6
, which is all well and good, but how do I override this feature, so that the file is indeed deleted to?
From the shell there exists no problem:
from myapp.models import UserProfile
user1==UserProfile.objects.all()[0]
user1.avatar.delete()
Removes the jpeg
too.
EDIT:
I tried using a signal like:
#models.py
.
.
.
@receiver(post_delete, sender=UserProfile)
def avatar_post_delete_handler(sender, **kwargs):
print 'DEBUG: avatar delete triggered'
avatar = kwargs['instance']
storage, path = avatar.original_image.storage, avatar.original_image.path
storage.delete(path)
but this did not even trigger, I guess because I'm not deleting the UserProfile
object
in its entirety when the user selects the clear checkbox, but rather just the avatar.
Extend the ImageField like this and use it instead:
class ImageField(models.ImageField):
def save_form_data(self, instance, data):
if data is not None:
file = getattr(instance, self.attname)
if file != data:
file.delete(save=False)
super(ImageField, self).save_form_data(instance, data)
This will delete the old file if you replace it with the new one, or mark it to clear. Here is the explanation why.
Edit:
There is also an app django-smartfields that includes this functionality plus more, like automatic re-sizing, automatic conversion of images and videos, etc. It achieves it in a more complicated way though, using field descriptors and model customization. But it is very simple to use:
from smartfields import fields
class UserProfile(models.Model):
avatar = fields.ImageField(upload_to='avatars', blank=True)
It will also remove files whenever:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With