我正在尝试使用以下方案:
当GET请求进入我的“/”路由时,我通常想用我的HomeView处理它。但是,我的网站是重型AJAX所以如果请求的UserAgent是一个机器人,那么我用一个完全呈现的页面版本(标准的PhantomJS东西)来提供它。该方法工作正常,但完全呈现版本的性能和该版本的SLA与常规用户视图非常不同。因此,我想使用一块中间件来进行机器人检测,然后根据该中间件我将请求发送到另一个视图。
中间件部分很简单,我有一个process_request处理程序来检测机器人 - 没什么大不了的。但是,我无法想象覆盖将要调用的View函数的任何选项。在Django中有一种“正确”的方法吗?我目前的想法是:
注意:
答案 0 :(得分:2)
这不是您问题的直接答案("将请求重新发送到其他视图"),但也许此解决方案可能会解决您的问题。
首先,保留中间件,但仅用它来检测访问者是否是机器人:
def process_request(self, request):
request.is_bot = is_bot(request) # assuming you have a function for detecting bots
return
然后创建一个基于类的视图,在request.is_bot
为True时调用特定方法:
class BotViewMixin(object):
def dispatch(self, request, **kwargs):
if request.is_bot:
return self.handle_bot()
return super(BotViewMixin, self).dispatch(request, **kwargs)
然后,您可以在任何需要的地方继承此视图(例如,您的主页视图)。您只需在视图上创建handle_bot
方法,即可返回您对机器人的响应。
此解决方案的优点:
虽然没有经过测试,但您可能需要调整代码。
编辑:
由于您使用NewRelic并且必须使用机器人的专用视图才能获得准确的统计信息,因此这种方法不适合您。
您可以使用中间件,并且仍然可以使所有中间件正常工作。您只需将自己的中间件放在MIDDLWARE_CLASSES中:
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'yourproject.CrawlerDetector',
)
另外,我认为您应该编写两个中间件方法:process_request
用于检测机器人,process_view
用于将机器人重定向到专用视图。
以下代码可能适用于您的情况:
from django.core.urlresolvers import reverse
class CrawlerDetector(object):
def process_request(self, request):
"""detect if the user agent is a bot"""
user_agent = request.META.get('HTTP_USER_AGENT', "")
request.is_bot = self.is_crawler(user_agent)
return
def process_view(request, view_func, view_args, view_kwargs):
if request.is_bot and request.path == reverse('home_page'):
return HtmlRendererView().get(request)
return
答案 1 :(得分:0)
我目前的工作解决方案虽然没有Eliot建议的解决方案那么干净,但看起来(基本上)是这样的:
class CrawlerDetector(object):
# Middleware that detects requests that should be rendered by the HtmlRendererView.
def process_request(self, request):
user_agent = request.META.get('HTTP_USER_AGENT', "")
if not self.is_crawler(user_agent):
return None
return HtmlRendererView().get(request)
它具有从流中删除任何下游中间件的缺点,但它允许我在根视图路由到之前调用我的特定于爬虫的视图。