title: How to install a custom upload handler in a Django generic view?
body: <p>In order to provide progress feedback of file uploads I need to install a custom upload handler for a specific view. This is documented for "classical" Django views at </p>
  
  <p><a href="https://docs.djangoproject.com/en/dev/topics/http/file-uploads/#modifying-upload-handlers-on-the-fly" rel="nofollow">https://docs.djangoproject.com/en/dev/topics/http/file-uploads/#modifying-upload-handlers-on-the-fly</a></p>
  
  <p>For <a href="https://docs.djangoproject.com/en/dev/ref/generic-views/" rel="nofollow">generic views</a>, however, I could not find any instructions and I came up with the following:</p>
  
  <pre class="lang-py prettyprint-override"><code>from django.utils import importlib
  from django.core.exceptions import ImproperlyConfigured
  from django.views.decorators.csrf import csrf_protect
  
  class UploadHandlerMixin(object):
      '''
          A mixin for Django generic views that installs a custom upload handler in front of
          the current chain of upload handlers.
  
          You specify the handler to install by overriding the 'upload_handler' attribute of
          the class, specifying the module and class name in the form 'path.to.module.class':
  
              class MyView(UploadHandlerMixin, View):
                  upload_handler = 'path.to.module.MyUploadHandler'
  
          If you do not override 'upload_handler', no additional upload handler will be
          installed.
  
          If the CsrfViewMiddleware is installed (which is the default) then you must use
          your view as follows in your urls.py:
  
              from django.views.decorators.csrf import csrf_exempt
              url(r'^.../$', csrf_exempt(MyView.as_view()), ...),
  
          Internally, the UploadHandlerMixin mixin will install the upload handler and then
          perform the CSRF check. (This is necessary because the CSRF check inspects
          request.POST, and afterwards upload handlers cannot be changed, see documentation
          link given below.)
  
          The handler is installed as described in the Django documentation "Modifying upload handlers
          on the fly", see https://docs.djangoproject.com/en/dev/topics/http/file-uploads/#modifying-upload-handlers-on-the-fly
      '''
  
      upload_handler = None
  
      def dispatch(self, request, *args, **kwargs):
          if not self.upload_handler is None:
              request.upload_handlers.insert(0, UploadHandlerMixin._instantiate_upload_handler(self.upload_handler, request))
          return _uploadhandler_dispatch(request, self, *args, **kwargs)
  
      @staticmethod
      def _instantiate_upload_handler(path, *args, **kwargs):
          i = path.rfind('.')
          module, attr = path[:i], path[i+1:]
          try:
              mod = importlib.import_module(module)
          except ImportError, e:
              raise ImproperlyConfigured('Error importing upload handler module %s: "%s"' % (module, e))
          except ValueError, e:
              raise ImproperlyConfigured('Error importing upload handler module. Is FILE_UPLOAD_HANDLERS a correctly defined list or tuple?')
          try:
              cls = getattr(mod, attr)
          except AttributeError:
              raise ImproperlyConfigured('Module "%s" does not define a "%s" upload handler backend' % (module, attr))
          return cls(*args, **kwargs)
  
  @csrf_protect
  def _uploadhandler_dispatch(request, view, *args, **kwargs):
      return super(UploadHandlerMixin, view).dispatch(request, *args, **kwargs)
  </code></pre>
  
  <p>Is this the "recommended way" to accomplish the task? Is it okay security-wise?</p>