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

chr*_*kso 4 python django redirect http-headers turbolinks

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

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

但是,Turbolinks使用发出请求XMLHttpRequest,该请求透明地跟随重定向。Turbolinks无法在没有服务器额外配合的情况下判断请求是否导致了重定向。

解决方案是:

发送Turbolinks-Location标头以响应被重定向的访问,Turbolinks将用您提供的值替换浏览器的最高历史记录条目。

Turbolinks Rails引擎针对通过redirect_to助手重定向的非GET XHR请求自动执行此优化。

我对在Django(1.11)项目上使用Turbolinks感兴趣,我想知道是否有人可以向我指出如何创建新的Django redirect()函数或修改现有函数以始终包含Turbolinks的正确方向-重定向到预期功能所需的位置标头。我绝对不希望每次重定向时都手动设置此标头。

在“提交表单后重定向”部分中有一个类似的条目(https://github.com/turbolinks/turbolinks#redirecting-after-a-form-submission),对于理解如何实现的任何帮助,我也将不胜感激:

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

Turbolinks Rails引擎针对通过redirect_to助手重定向的非GET XHR请求自动执行此优化。

我确实在github上看到一个“为Django引入Turbolinks实现”程序包,但这是从turbolinks-classic派生的,并且源代码没有提及Turbolinks-Location标头,因此我确定这不是我想要的。

chr*_*kso 5

我确实通过被reddit 指向该项目中的一滴代码来发现我到底要怎么做,该怎么做呢用户。

我将TurbolinksMiddleware类复制到我自己的apps目录下的Middleware.py中,并在我的settings.py中列出了该类

# MIDDLEWARE CONFIGURATION
# --------------------------------------------------------------------------
MIDDLEWARE = [
    .
    .
    .
    'apps.middleware.TurbolinksMiddleware',
]
Run Code Online (Sandbox Code Playgroud)

通过在我的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
Run Code Online (Sandbox Code Playgroud)