1

I have two modelforms--one includes a standard ImageField and the other is an inlineformset of ImageFields.
The normal standard ImageField renders on the page with the option for "Clear[ing]" while the inlineformset ImageFields render with an optional "Delete" tickbox.
Either Clear or Delete will remove the image from the User's profile, but the actual image file will remain in storage, as well as the URL to the image.
I am trying to remove all associations to the image once the User updates his Profile form by "clearing" or "deleting" the image.
I found FieldFile.delete which I believe just requires me to call .delete() on the instance, but I'm not sure how to conditionally check whether the user is updating the form with the "delete" box or "clear" box ticked.

Here are the two models containing the image fields:

class Profile(models.Model):
    profile_photo = models.ImageField(
        upload_to=profile_photo_upload_loc,
        null=True,
        blank=True,
        verbose_name='Profile Image',
    )  

class CredentialImage(models.Model):
    profile = models.ForeignKey(Profile, default=None,
        related_name='credentialimage')
    image = models.ImageField(
        upload_to=credential_photo_upload_loc,
        null=True,
        verbose_name='Image Credentials',
    )  

The ModelForms:

class ProfileUpdateForm(ModelForm):
    class Meta:
        model = Profile
        fields = [
            "profile_photo",
        ]

class CredentialImageForm(ModelForm):
    image = ImageField(required=False, widget=FileInput)

    class Meta:
        model = CredentialImage
        fields = ['image', ]

CredentialImageFormSet = inlineformset_factory(Profile,
    CredentialImage, fields=('image', ), extra=2)

The view:

class ProfileUpdateView(LoginRequiredMixin, UpdateView):
    form_class = ProfileUpdateForm

    def get_context_data(self, **kwargs):
        data = super(ProfileUpdateView, self).get_context_data(**kwargs)
        if self.request.POST:
            data['credential_image'] = CredentialImageFormSet(self.request.POST, self.request.FILES, instance=self.object)
        else:
            data['credential_image'] = CredentialImageFormSet(instance=self.object)
        return data

    def get_object(self, *args, **kwargs):
        user_profile = self.kwargs.get('username')
        obj = get_object_or_404(Profile, user__username=user_profile)
        return obj

    def form_valid(self, form):
        data = self.get_context_data()
        formset = data['credential_image']
        if formset.is_valid():
            self.object = form.save()
            formset.instance = self.object
            formset.save()
            return redirect(self.object.get_absolute_url())
        else:
            print("WTF")    

        instance = form.save(commit=False)
        instance.user = self.request.user
        return super(ProfileUpdateView, self).form_valid(form)   

My View is all kinds of messed up but it seems to work. Now looking to completely remove the image files from storage upon update.

Jay Jung
  • 1,805
  • 3
  • 23
  • 46
  • Duplicate of [How do I get Django Admin to delete files when I remove an object from the database/model?](https://stackoverflow.com/questions/5372934/how-do-i-get-django-admin-to-delete-files-when-i-remove-an-object-from-the-datab) – xyres Nov 11 '17 at 07:30

1 Answers1

1

Use Django-cleanup:

pip install django-cleanup

settings.py

INSTALLED_APPS = (
    ...
    'django_cleanup', # should go after your apps
    ...
)
Raj Shah
  • 668
  • 1
  • 9
  • 23