我想为应用内重定向创建一个不完全重定向的机制,但只需加载另一个视图功能。所以,让我们说我正在进行localhost:8000/a
,django呈现视图和视图的最后一行说
return HttpResponseRedirect('/b')
所以现在我的浏览器会转到localhost:8000/b
,django将呈现视图并将其返回给我。
现在我想只在服务器端这样做。因此,当我转到localhost:8000/a
并且django决定重定向到/b
时,它会呈现/b
的视图,将其推送到所有中间件等(因此就像重定向一样)并返回响应任何重定向(如用户所见)。
我已经调用了这样的重定向HttpResponseSmartRedirect
,它看起来就像那样:
class HttpResponseSmartRedirect(HttpResponseRedirect):
pass
现在我想为此创建中间件(作为所有中间件的最后一个运行),process_response
上的中间件检查响应是否是类HttpResponseSmartRedirect
的实例。现在我的问题是 - 当我遇到这种情况时 - 如何使用url中的视图实际生成响应?我可以使用resolve()
中的urlsolvers
轻松获取查看功能,但我不知道如何强制它通过所有中间件并创建与我获得的响应完全相同的响应随意重定向。最糟糕的做法是只调用urllib2.get(url)
,但该行的外观让我想破坏我的电脑。
关于如何在不调用丑陋urllib
的情况下做得很好的任何想法?
答案 0 :(得分:1)
您需要在Django请求处理代码的底部重新注入原始请求。
请求从BaseHandler.get_response
的{{1}}开始处理。
所以解决方案就像(未经测试!):
django.core.handlers.base
对于实际使用,您需要一些防止重定向循环和无限递归的保护。
或者你可以用不同的方式解决问题 - 让浏览器根据重定向进行重新获取。如果需要隐身,那么使用一些客户端Javascript就可以轻松实现。
答案 1 :(得分:0)
BaseHandler示例(不带重定向的斜杠,请使用它代替CommonMiddleware,Django 2.1):
from django.http import HttpResponsePermanentRedirect, HttpRequest
from django.core.handlers.base import BaseHandler
from django.middleware.common import CommonMiddleware
from django.conf import settings
class HttpSmartRedirectResponse(HttpResponsePermanentRedirect):
pass
class CommonMiddlewareAppendSlashWithoutRedirect(CommonMiddleware):
""" This class converts HttpSmartRedirectResponse to the common response
of Django view, without redirect.
"""
response_redirect_class = HttpSmartRedirectResponse
def __init__(self, *args, **kwargs):
# create django request resolver
self.handler = BaseHandler()
# prevent recursive includes
old = settings.MIDDLEWARE
name = self.__module__ + '.' + self.__class__.__name__
settings.MIDDLEWARE = [i for i in settings.MIDDLEWARE if i != name]
self.handler.load_middleware()
settings.MIDDLEWARE = old
super(CommonMiddlewareAppendSlashWithoutRedirect, self).__init__(*args, **kwargs)
def process_response(self, request, response):
response = super(CommonMiddlewareAppendSlashWithoutRedirect, self).process_response(request, response)
if isinstance(response, HttpSmartRedirectResponse):
if not request.path.endswith('/'):
request.path = request.path + '/'
# we don't need query string in path_info because it's in request.GET already
request.path_info = request.path
response = self.handler.get_response(request)
return response