要将Turbolinks 5与Django一起使用,如何在使用redirect()时自动包含Turbolinks-Location标头?

时间:2017-11-11 17:26:55

标签: python django redirect http-headers turbolinks

根据Turbolinks 5关于“关注重定向”的文档(https://github.com/turbolinks/turbolinks#following-redirects):

  

当您访问位置/one并且服务器将您重定向到位置时   /two,您希望浏览器的地址栏显示重定向   URL。

     

但是,Turbolinks使用XMLHttpRequest发出请求   透明地遵循重定向。 Turbolinks没办法说出来   请求是否导致重定向而没有额外的   来自服务器的合作。

解决方法是:

  

发送Turbolinks-Location标头以响应访问时间   重定向,Turbolinks将取代浏览器的最高历史   具有您提供的价值的条目。

     

Turbolinks Rails引擎会自动为使用redirect_to帮助程序重定向的非GET XHR请求执行此优化。

我非常有兴趣在我的Django(1.11)项目中使用Turbolinks,我想知道是否有人能指出我正确的方向如何创建一个新的Django redirect()函数或修改现有的函数包括重定向按预期运行所需的Turbolinks-Location标头。我绝对不希望每次进行重定向时都手动设置此标题。

“表格提交后重定向”部分(https://github.com/turbolinks/turbolinks#redirecting-after-a-form-submission)中有类似的条目我还非常感谢您在理解如何实施方面的任何帮助:

  

如果表单提交导致服务器上的状态更改   影响缓存页面,请考虑清除Turbolinks的缓存   Turbolinks.clearCache()

     

Turbolinks Rails引擎自动执行此优化   对于使用redirect_to帮助程序重定向的非GET XHR请求。

我确实看到github上有一个“用于Django的Drop-in turbolinks实现”包,但这是来自turbolinks-classic,而源代码没有提到Turbolinks-Location标题所以我确信这不是我的意思我正在寻找。

2 个答案:

答案 0 :(得分:5)

我最终发现了如何通过reddit用户指向此项目https://github.com/viewflow/django-material/blob/v2/material/middleware.py中的一小段代码来完成我正在尝试的操作。

我在我的apps目录下将TurbolinksMiddleware类复制到我自己的middleware.py中,并将其列在我的settings.py中

# MIDDLEWARE CONFIGURATION
# --------------------------------------------------------------------------
MIDDLEWARE = [
    .
    .
    .
    'apps.middleware.TurbolinksMiddleware',
]

通过在我的html模板中包含turbolinks.js的常规安装步骤,一切似乎都正常工作。

以下是TurbolinksMiddleware类,以防它在上面的链接中不可用:

class TurbolinksMiddleware(object):
    """
    Send the `Turbolinks-Location` header in response to a visit that was redirected,
    and Turbolinks will replace the browser’s topmost history entry .
    """

    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)

        is_turbolinks = request.META.get('HTTP_TURBOLINKS_REFERRER')
        is_response_redirect = response.has_header('Location')

        if is_turbolinks:
            if is_response_redirect:
                location = response['Location']
                prev_location = request.session.pop('_turbolinks_redirect_to', None)
                if prev_location is not None:
                    # relative subsequent redirect
                    if location.startswith('.'):
                        location = prev_location.split('?')[0] + location
                request.session['_turbolinks_redirect_to'] = location
            else:
                if request.session.get('_turbolinks_redirect_to'):
                    location = request.session.pop('_turbolinks_redirect_to')
                    response['Turbolinks-Location'] = location
        return response

答案 1 :(得分:0)

您提到的django包实现了middleware,负责添加标头。似乎对于旧的turbolinks,标题有不同的名称。您可以编写自己的中间件来支持turbolinks 5。

  

不是正常提交​​表格,而是使用XHR提交表格。

你可以用普通的django实现这一点。阅读django CSRF doc - 他们详细解释了什么是必要的。