title: Django process_view middleware: how to deal with exceptions in views
body: <p>I'm trying to wrap my head around a correct, workable implementation of <code>process_view</code>. The idea is to call the view function in <code>process_view</code>. My problem is mainly how to deal with exceptions in the view function.</p>
  
  <p>It is my understanding that middleware functions may never raise exceptions, so all exceptions that are possibly thrown by the view function must be caught. This understanding is indeed confirmed in practice: if I don't catch the exception, Django's base handler will skip any process_exception calls. However, if I do catch the exception, the view function will be called twice (once by my middleware, and once again by the base handler in an attempt to run into the exception so it can be processed by the various middleware's <code>process_exception</code>). In the snipplet below, the first call is in <code>response = middleware_method(...</code> and the second call is in <code>response = callback(...</code>. </p>
  
  <p>A snipplet from Django 1.4's django/core/handlers/base.py:</p>
  
  <pre><code>    # Apply view middleware
      for middleware_method in self._view_middleware:
          response = middleware_method(request, callback, callback_args, callback_kwargs)
          if response:
              break
  
  if response is None:
      try:
          response = callback(request, *callback_args, **callback_kwargs)
      except Exception, e:
          # If the view raised an exception, run it through exception
          # middleware, and if the exception middleware returns a
          # response, use that. Otherwise, reraise the exception.
          for middleware_method in self._exception_middleware:
              response = middleware_method(request, e)
              if response:
                  break
          if response is None:
              raise
  </code></pre>
  
  <p>For extra clarity, this is my middleware:</p>
  
  <pre><code>class MyMiddleware(object):
  
      def process_view(self, request, view_func, view_args, view_kwargs):
          # ... do stuff
  
          try:
              response = view_func(request, *view_args, **view_kwargs)
          except:
              return None
  
          # or, alternatively (but this has its own set of problems)
          response = view_func(request, *view_args, **view_kwargs)
  
          # do more stuff
  </code></pre>