有没有办法通过自定义 HTTP header 获得引用 URL?

Is there a way to get a referring URL via a custom HTTP header?

我目前正在使用以下功能来获取参考视图:

def get_referer_view(request, default=None):   
    referer = request.META.get('HTTP_REFERER')
    if not referer:
        return default

    # remove the protocol and split the url at the slashes
    referer = re.sub('^https?:\/\/', '', referer).split('/')
    if referer[0] != request.META.get('SERVER_NAME'):
        return default

    # add the slash at the relative path's view and finished
    referer = u'/' + u'/'.join(referer[1:])
    return referer

如果我根据程序逻辑重定向 view,例如...

return HttpResponseRedirect('dashboard')

...有没有办法在不使用 HTTP_REFERER 的情况下获取引用视图,以便我可以在重定向的 view 中使用该变量?这并不总是在浏览器的 header 中设置。

请注意,因为视图是通过编程重定向的,所以我无法使用 POST 来收集数据。

也许可以通过某种方式设置和检索自定义 header?

使用Django的中间件组件。

https://docs.djangoproject.com/en/3.0/topics/http/middleware/

像这样的东西应该可以工作:

class HTTPReferer:

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

def __call__old(self, request):
    # old
    referer = request.META.get('HTTP_REFERER', None)
    request.referer = referer
    # other business logic as you like it
    response = self.get_response(request)
    return response

def __call__(self, request):
    # reflecting last edit
    path = request.path
    response = self.get_response(request)
    response['previous_path'] = path
    return response

所以你可以将你需要的任何信息绑定到 Django 中的每个 request/response 周期(你也可以设置自定义 headers,等等...)

在上面的示例中,HTTP_REFERER 将在请求 object 中作为 referer 可用。

编辑:我认为,您担心的是 HTTP_REFERER 并不总是由客户端填充;所以你可以打领带 HttpRequest.path to every request made to a custom header. If path is not enough, you could save the request args too. That's all, I think. Then you have a custom header populated by the last path. Further on, if this is not enough, you could use Django's URL resolver.

既然您控制了发出请求的页面,那当然可以。将当前的 URL 添加到某些 header 并在您的函数中提取它,类似于: Add request header before redirection

所以不是这个:

def current_view():
   ...
   return HttpResponseRedirect('dashboard')

做这样的事情:

def current_view():
    ...
    response = redirect('/dashboard')
    response['source-view'] = request.resolver_match.view_name
    return response

这应该会生成带有自定义 header source-view 的 302,您可以在接收视图中提取它

对于那些感兴趣的人,这是我得出的解决方案。诀窍是在第一次请求存储 view_namepath 之后设置一个 cookie,然后在呈现视图之前调用它并保存到 request

class MyMiddleware:

    def __init__(self, get_response):
        # One-time configuration and initialization.
        self.get_response = get_response

    def __call__(self, request):
        # Code to be executed for each request before
        # the view (and later middleware) are called.

        # Add the referer cookie be accessible in request.response
        request.referer_view = request.COOKIES.get('referer_view', None)
        request.referer_path = request.COOKIES.get('referer_path', None)
        print('request.referer_view', request.referer_view)
        print('request.referer_path', request.referer_path)

        response = self.get_response(request)
        # Code to be executed for each request/response after
        # the view is called.

        # Set a cookie with the current view name that is cleared each time the view changes
        response.set_cookie('referer_view', request.resolver_match.view_name)
        response.set_cookie('referer_path', request.path)

        return response

每次更改视图时,值都会在此循环中更新。