问题
How do you catch a specific exception during Django template rendering in a class based view?
I have a custom exception ImmediateHttpResponse which is intended to cause an immediate redirect in my class based view. I have tried:
def dispatch(self, *args, **kwargs):
try:
return super(AppConnectionsView, self).dispatch(*args, **kwargs)
except ImmediateHttpResponse as e:
return HttpResponseRedirect(e.response)
The exception I am trying to catch is raised in a template tag and so it seems the exception is intercepted by django's template debug and I get a template render error HttpResponseRedirect no exception supplied. I still want to debug my templates, just not when HttpResponseRedirect is raised.
Please hold all comments about not raising errors in template tags... I have an extremely good reason.
回答1:
If you really have to do it at any cost, here is a simple solution:
def dispatch(self, *args, **kwargs):
response = super(AppConnectionsView, self).dispatch(*args, **kwargs)
try:
response.render()
except ImmediateHttpResponse as e:
return HttpResponseRedirect(e.response)
return response
The reason why you cannot catch render errors in the view is because although response is created in the view, it is actually rendered by BaseHandler, which handles all errors appropriately. Downside of above solution is that it will render the template twice per request.
The only other way to be able to catch your custom error is to customize the BaseHandler (or it's derivative, like a WSGIHandler), which obviously would eliminate that double rendering issue.
Say you are using wsgi, as you probably should :) you can do something like that:
import django
from django.utils import six
from django.core.handlers.wsgi import WSGIHandler as DjangoWSGIHandler
from my_app.exceptions import ImmediateHttpResponse
class WSGIHandler(DjangoWSGIHandler):
def handle_uncaught_exception(self, request, resolver, exc_info):
(type, value, traceback) = exc_info
if type is not None and issubclass(type, ImmediateHttpResponse):
six.reraise(*exc_info)
return super(WSGIHandler, self).handle_uncaught_exception(
request, resolver, exc_info)
def get_wsgi_application():
django.setup()
return WSGIHandler()
Now you can use this function in wsgi.py:
application = get_wsgi_application()
来源:https://stackoverflow.com/questions/27210643/django-how-to-catch-a-specific-exception-in-a-class-based-view-during-template