Hunter Ford Hunter Ford

How to Handle HTTP Redirects with Jquery and Django

Jquery has a funny way of handling 302 redirects during AJAX calls. These frequently come up when I need to redirect a user to a login page. Here's how I'm handling it with Django.

The underlying problem we experience with redirects in Jquery is that the redirects are followed. So instead of getting a status code of HTTP/1.1 302 Found, we get HTTP/1.1 200 OK. So one way to get around this is to return a made up status code. This is easily accomplished with a middleware in django.

from django.http import HttpResponseRedirect

class AjaxRedirect(object):
    def process_response(self, request, response):
        if request.is_ajax():
            if type(response) == HttpResponseRedirect:
                response.status_code = 278
        return response

Make sure to add the new middleware to settings.py.

'apps.main.middleware.AjaxRedirect'

And the final piece of the puzzle is to add a global AJAX complete handler, that checks for the new status code, redirects the page to the Location header in the HTTP response, and replace the next query variable. The last part is important because the login_required decorator automatically sets the next query variable to the HTTP Referrer, which in this case would be the URL of the AJAX call. So we want to replace it with the page we're currently on.

$(document).ready(function() {
    $('body').ajaxComplete(function(e, xhr, settings) {
        if (xhr.status == 278) {
            window.location.href = xhr.getResponseHeader("Location").replace(/\?.*$/, "?next="+window.location.pathname);
        }
    });
});

Comments

  • Oli

    The StackOverflow favourite answer involves turning all your data into JSON and handling that through $.ajax(). This solution is about a hundred-billion times easier to implement (you can keep $.load()) and just works. Thanks to you and thanks for Django's middleware for making this simple.
  • view

    How to handle http redirects with jquery and django.. Ho-o-o-o-t :)
  • Jani Tiainen

    It's not jquery but HTTP client (browser in this particular case) that is required to do transparent redirect according to HTTP specification. This is generic ajax problem and there is several solutions, including custom headers and different response codes in a body. Personally I wouldn't recommend this solution - even it feels pretty simple it's invasive. It intercepts all ajax redirects - which not may be desired. Better and more precise results can be obtaining by using writing simple custom decorator to replace @login_required