Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Hidden Redirection

Tags:

python

django

I want to create a mechanism for in-app redirecting that would not quite redirect, but just load another view function. So let's say I'm going on localhost:8000/a, django renders the view and last line of the view says

return HttpResponseRedirect('/b')

So now my browser would go to localhost:8000/b, django would render view and return it to me.

Now I want to do that only on server side. So when I go to localhost:8000/a and django decides to redirect to /b, it renders view for /b, pushing it through all middlewares etc (so just like redirection would work) and return response without any redirections at all (as seen for user).

I have called such redirection HttpResponseSmartRedirect and it looks just like that:

class HttpResponseSmartRedirect(HttpResponseRedirect):
    pass

Now I want to create middleware for that (that runs as last of all middlewares), that on process_response checks if the response is instance of class HttpResponseSmartRedirect. Now my problem is - when I run into that situation - how to actually generate response with the view from the url? I can easily get view function by using resolve() from urlsolvers, but I don't know how to force it to go through all middlewares and create response identical to the one I'd get with casual redirection. The nastiest way of doing it is to just call urllib2.get(url), but the looks of that line makes me want to destroy my computer.

Any ideas of how I can do it nicely without calling ugly urllib's?

like image 357
Gricha Avatar asked Feb 15 '26 08:02

Gricha


1 Answers

You'll need to re-inject the original request at the bottom of the Django request processing code.

Requests are processed starting at BaseHandler.get_response in django.core.handlers.base.

So the solution would be something like (untested!):

from django.core.handlers.base import BaseHandler

class SmartRedirectMiddleware(object):
    def process_response(self, request, response):
        if isinstance(response, HttpSmartRedirectResponse):
           handler = BaseHandler()
           request.url = response.redirect_url
           resp = handler.get_response(request)
           return resp

For real use, you'd want some protection against redirect loops and infinite recursion.

Or you could solve the problem differently - let the browser do the re-fetch based on the redirect. If that needs to be invisible, it's easy enough to achieve with some client side Javascript.

like image 67
Malcolm Box Avatar answered Feb 16 '26 21:02

Malcolm Box



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!