I have a Django project where I'm using a view to handle different HTTP methods. The POST
handled the creation of an object and then redirected to the same view as a GET
(or so I thought), using Django's redirect()
shortcut (HTTPResponseRedirect
) to return the newly created object. This worked fine. I tried the same thing with a PUT
but I fell into a redirect loop. After scratching my head for a while I stumbled across this SO answer and then I inferred that since redirect doesn't handle the POST
data, the request turns into a GET
.
I confirmed this by watching the logs when I do the redirect from a POST
:
[15/Dec/2014 00:47:43] "POST /client/151/ HTTP/1.1" 302 0
[15/Dec/2014 00:47:43] "GET /client/151/ HTTP/1.1" 200 395
However the PUT
stays a PUT
and throws me into a redirect loop until it errors out.
[14/Dec/2014 23:07:36] "PUT /api/asset/6779 HTTP/1.1" 301 0
[14/Dec/2014 23:07:37] "PUT /api/asset/6779/ HTTP/1.1" 302 0
[14/Dec/2014 23:07:37] "PUT /api/asset/6779 HTTP/1.1" 301 0
[14/Dec/2014 23:07:38] "PUT /api/asset/6779/ HTTP/1.1" 302 0
[14/Dec/2014 23:07:38] "PUT /api/asset/6779 HTTP/1.1" 301 0
[14/Dec/2014 23:07:39] "PUT /api/asset/6779/ HTTP/1.1" 302 0
[14/Dec/2014 23:07:39] "PUT /api/asset/6779 HTTP/1.1" 301 0
[14/Dec/2014 23:07:40] "PUT /api/asset/6779/ HTTP/1.1" 302 0
[14/Dec/2014 23:07:40] "PUT /api/asset/6779 HTTP/1.1" 301 0
[14/Dec/2014 23:07:41] "PUT /api/asset/6779/ HTTP/1.1" 302 0
[14/Dec/2014 23:07:41] "PUT /api/asset/6779 HTTP/1.1" 301 0
[14/Dec/2014 23:07:42] "PUT /api/asset/6779/ HTTP/1.1" 302 0
Shouldn't the redirect use GET
? I understand what's going on but not sure why? What gives?
EDIT
# urls.py
url(r'^$', views.put_vs_post_redirect),
# views.py
from django.shortcuts import redirect
def put_vs_post_redirect(request, asset_id):
if request.method == 'GET':
return HTTPResponse('Get request')
elif request.method == 'POST':
return redirect('/')
elif request.method == 'PUT':
return redirect('/')
HttpResponseRedirect is a subclass of HttpResponse (source code) in the Django web framework that returns the HTTP 302 status code, indicating the URL resource was found but temporarily moved to a different URL. This class is most frequently used as a return object from a Django view.
Django Redirects: A Super Simple Example Just call redirect() with a URL in your view. It will return a HttpResponseRedirect class, which you then return from your view. Assuming this is the main urls.py of your Django project, the URL /redirect/ now redirects to /redirect-success/ .
Django uses request and response objects to pass state through the system. When a page is requested, Django creates an HttpRequest object that contains metadata about the request. Then Django loads the appropriate view, passing the HttpRequest as the first argument to the view function.
As already suggested by @mdegis you can use the Django redirect function to redirect to another view or url. You can pass positional or keyword argument(s) to the redirect shortcut using the reverse() method and the named url of the view you're redirecting to.
As mentioned in the comments, this is entirely dependent on the client, and not all clients handle redirects in the same way. You can find a decent explanation of the redirect codes and why a 301 should drop POST data on Stack Overflow.
When working with a 301
(and often a 302
) redirect, most browsers will discard POST
data and make a GET
request. This is mostly because browsers have always done this, and POST
requests most commonly come from web forms, so it makes sense that the redirect results in a GET
, allowing for the browser to display a different page without interfering. This is not the case for things like PUT
or PATCH
requests, as they cannot currently be sent by web forms and typically play by different rules.
If you are looking to maintain the POST
data on a 302
redirect, you should consider using a 307
redirect instead. A 307
request should maintain the request method, and the request body as a result.
If you are looking to maintain the POST
data in a 301
redirect, there is currently a draft for a 308
status code that would work like the 307
, but be permanent.
You can force the redirect to use a GET
request with a 303
redirect. It works very much like a 302
, but it enforces that the request method is always a GET
request. It's often used in APIs for asynchronous tasks.
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