【问题标题】:To use Turbolinks 5 with Django, how can I automate inclusion of the Turbolinks-Location header when using redirect()?要将 Turbolinks 5 与 Django 一起使用,如何在使用 redirect() 时自动包含 Turbolinks-Location 标头?
【发布时间】:2017-11-11 17:26:54
【问题描述】:

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

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

但是,Turbolinks 使用XMLHttpRequest 发出请求,这 透明地遵循重定向。 Turbolinks 无法分辨 请求是否导致重定向而无需额外 来自服务器的合作。

解决办法是:

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

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

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

在“提交表单后重定向”部分有一个类似的条目 (https://github.com/turbolinks/turbolinks#redirecting-after-a-form-submission) 我也希望能在理解如何实施方面提供任何帮助:

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

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

我确实看到 github 上有一个“Drop-in turbolinks implementation for Django”包,但这是从 turbolinks-classic 分叉的,源代码没有提到 Turbolinks-Location 标头,所以我确定这不是我的我正在寻找。

【问题讨论】:

    标签: python django redirect http-headers turbolinks


    【解决方案1】:

    我确实最终发现了如何做我正在尝试的事情,因为我被一个 reddit 用户指向了这个项目中的代码块https://github.com/viewflow/django-material/blob/v2/material/middleware.py

    我将 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
    

    【讨论】:

      【解决方案2】:

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

      不要正常提交表单,而是使用 XHR 提交。

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

      【讨论】:

        猜你喜欢
        • 2013-01-25
        • 1970-01-01
        • 2013-10-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多