How to delete an uploaded image with a html button in Django?

Viewed 512

How can I delete an uploaded image from my updateview template? I tried using <input type="checkbox" onchange="submit();" name="{{ object.image }}-clear" id="{{ object.image }}-clear_id"> to remove the image but with no success.

I have django_cleanup in INSTALLED_APPS so I am just looking for a simple method to remove the image from my object and return to the currrent update view.

Code:

models.py:

class Report(models.Model):

    image = models.FileField(storage=PublicMediaStorage(), blank=True)

forms.py:

class ReportCreate(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(ReportCreate, self).__init__(*args, **kwargs)

    class Meta:
        model = Report

        fields = ['image']
        widgets = {'image': forms.FileInput(attrs={'onchange': 'submit();'}),}

Views.py:

class ReportView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):

    model = Report

    template_name = 'myapp/report_update.html'
    form_class = forms.ReportCreate

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)

urls.py:

urlpatterns = [
    path('report/<int:pk>/', ReportView.as_view(), name='report-view'),
]

html:

<img src="{{ object.image }}"/>
<input type="file" name="image" onchange="submit();" class="fileinput fileUpload form-control-file" id="id_image">
<input type="checkbox" onchange="submit();" name="{{ object.image }}-clear" id="{{ object.image }}-clear_id">
3 Answers

Update Report model

image = models.ImageField(storage=PublicMediaStorage(), null=True, blank=True)

In views.py

from django.views.generic import View

class ReportImageDeleteView(View):
    # you can either user POST, PUT or DELETE methods respectively 
    def get(self, request):

        report = Report.objects.get(id=self.kwargs.get('pk'))
        report.image = None
        report.save()

        return render(request, 'your_template.html')

# url
path(
    'report/<int:pk>/delete/',
    ReportImageDeleteView.as_view(),
    name='image-delete'
),

in template

<input type="checkbox" onchange="clearImage({{ object.id }});" name="{{ object.image }}-clear">

<script>
function clearImage(id) {
    var url = `/report/${id}/delete/`;
    window.location = url; // redirect
}
</script>

try this firstly edit your models.py like this so no one can upload any file except photos

class Report(models.Model):

    image = models.ImageField(storage=PublicMediaStorage(), blank=True)

then in your views.py

from django.shortcuts import redirect

 def delete_image(request, pk):
    query = Report.objects.get(pk=id)
    query.delete()
    return redirect("/report/<int:pk>/")

then urls.py

path('delete_image/(?P<pk>\d+)/', views.delete_image, name='delete_image')

and in your html

<a href="{% url 'delete_image' image.id %}">Delete</a>

Write an APIView which does this:

views.py

class RemoveImageFromReportView(APIView):
    """Removes only the image uploaded from the Report instance."""

    def delete(self, request, *args, **kwargs):

        report = Report.objects.get(id=kwargs['pk'])
        report.image.delete(save=True)
        report.save()
        return Response(data=None)

urls.py

urlpatterns = [
    path(
        "reports/<int:pk>/",
        views.RemoveImageFromReportView.as_view(),
        name="remove_image_from_instance",
    ),
]

On the html part. When the user clicks the delete image button make a ajax request to this endpoint with the instance id. Note that the api request made must be a DELETE method

If you want to delete the entire Report instance then use this link.

Related