2đź‘Ť
This is not a direct answer to your question (“Reroute a request to a different view”), but maybe this solution could adress your problem.
First, you keep your middleware, but use it only to detect if the visitor is a bot:
def process_request(self, request):
request.is_bot = is_bot(request) # assuming you have a function for detecting bots
return
Then you create a class based view that call a specific method when request.is_bot
is True:
class BotViewMixin(object):
def dispatch(self, request, **kwargs):
if request.is_bot:
return self.handle_bot()
return super(BotViewMixin, self).dispatch(request, **kwargs)
You can then inherit this view anywhere you need (e.g. for your Home Page View). You just have to create a handle_bot
method on your view, that will return your response for bots.
Advantages of this solution:
- You don’t need to write different views for bots, just create a dedicated method
- You don’t block other middlewares
- Your logic stay in your views (and not in your middleware)
This is not tested though, so you may need to adapt the code.
EDIT:
Since you use NewRelic and must use a dedicated view for bots in order to get accurate statistics, this approach won’t work for you.
You can go with the middleware thing, and still get all middlewares working. You just have to put your own middleware last in 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',
)
Also, I think you should write two middlewares methods: process_request
for detecting bots, and process_view
for redirecting bots to dedicated view.
The following code should probably work for your situation:
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
0đź‘Ť
My current working solution, while not as clean as Eliot’s suggested solution, looks (basically) like this:
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)
It has the downside of removing any downstream middleware from the flow, but it does allow me to call my crawler-specific View before the root View is routed to.
- [Django]-Why is there both a create_user and a _create_user method in django.contrib.auth.models.UserManager
- [Django]-How to use different database within same app in django?
- [Django]-Sphinx Note Block in a list under a code block?
- [Django]-How can I use a Django template tag for greater than on a forloop.counter?