Search code examples
pythonbackbone.jspyramid

Why isn't HTTPFound redirecting the page


I've got a Backbone application that doesn't redirect after a save. I don't know if this is something to do with Backbone or the server side code.

On the server:

url = request.route_url('test')
return HTTPFound(location=url)

I can see that location is correctly set to /test in the response headers. And following that there is a request with 200 OK to /test yet the page is not redirected.


Solution

  • Because you are saving by using an AJAX request (Backbone save documentation here: http://backbonejs.org/#Model-save) the client will not be redirected by the server response. This is not just because of Backbone, this is the nature of AJAX requests. If you want to redirect after a successful save you need to do that manually by setting a callback in the success option of the save. The success callback will given three arguments, model, response, and options (in that order), so you can use the response from the server to redirect.

    In your server, you should respond to a successful save with the saved model rendered as a JSON object. What I did to then redirect the page was I added the target location to the location attribute of the response header. You can get the xhr attribute from the options object in the success callback, and call getResponseHeader('location') on it to get the location and then direct the window there:

    model.save({}, {
      success: function(model, response, options){
        window.location = options.xhr.getResponseHeader('location');
      })
    });
    

    I'm not too familiar with Pyramid, so if someone wants to edit this answer with the best way to return a JSON object and modify the response location header in the server please do. According to these docs and these docs, it should look something like this:

    from pyramid.view import view_config
    
    class MyObject(object):
        def __init__(self, x):
            self.x = x
    
        def __json__(self, request):
            return {'x':self.x}
    
    @view_config(renderer='json')
    def object(request):
        request.response.location = "http://LocationToRedirectTo.com"
        return MyObject(1)
    
    # the JSON value returned by ``object`` will be:
    #    {"x": 1}
    

    And of course you need to change all that to actually save your object instead of creating the sample MyObject object.