I am trying to do POST tunneling on my Django website. What I am basically trying to do is to "enable" PUT and DELETE. So, now I am struggling with DELETE. In my template.html I have the following:
<form action="/photos/{{ photo.id }}/" method="POST" >
{% csrf_token %}
<button type="submit" class="btn btn-link" >Delete photo</button>
<input id="override" type="hidden" name="_method" value="DELETE"/>
</form>
In this way, I am trying to delete a photo by providing additional attribute "_method" to my request.POST.
I have written a middleware class that should be in charge of replacing "POST" with "DELETE" in my request:
class HTMLTunneling(object):
def process_request(self, request):
if request.POST.has_key('_method'):
http_method = request.POST['_method']
if http_method.lower() == 'put':
request.method = 'PUT'
request.META['REQUEST_METHOD'] = 'PUT'
request.PUT = QueryDict(request.body)
if http_method.lower() == 'delete':
request.method = 'DELETE'
request.META['REQUEST_METHOD'] = 'DELETE'
request.DELETE = QueryDict(request.body)
return None
But, django keeps throwing
Forbidden (403)
CSRF verification failed. Request aborted
every time I click my delete button. If I remove the middleware, it works. If I do anything that will disable the delete functionality, it works. I don't understand. Can anyone assist me with this?
Here is the view that is supposed to be processing this request:
@login_required
def handle_image(request, image_id):
"""
Main handler for an image. Checks what kind of a request came and redirects
traffic according to it.
"""
if request.method == 'GET':
return show_image(request, image_id)
elif request.method == 'DELETE':
return delete_image(request, image_id)
elif request.method == 'PUT':
# print("Inside put")
# update image with a like or comment
if request.PUT.has_key('publ'):
return privacy(request, image_id)
if request.PUT.has_key('like'):
return like_image(request, image_id)
if request.PUT.has_key('comm'):
return comment(request, image_id)
It actually just invokes the corresponding views. For example, the privacy view looks like this:
@login_required
def privacy(request, image_id):
try:
# user = CustomUser.objects.get(pk=user_id)
photo = Photo.objects.get(pk=image_id)
except:
raise Http404
accessor = request.user.customuser
if accessor != photo.owner:
return HttpResponseForbidden("Forbidden")
if request.PUT['publ'] == "true":
photo.public = True
photo.save()
elif request.PUT['publ'] == "false":
photo.public = False
photo.save()
c = image_context(photo, accessor)
return render(request, 'photos/view_image.html', c)
It just sets the image attribute to public or private. I did this by following advice from here and here. I don't have any AJAX stuff of course, only plain html.