Dear all,

In order to provide progress feedback of file uploads I needed to
install an upload handler for a specific view. This is documented for
"classical" views at

  
https://docs.djangoproject.com/en/dev/topics/http/file-uploads/#modifying-upload-handlers-on-the-fly

For generic views, however, I could not find any instructions and I
came up with the following, which I would like to share:

# BEGIN OF CLASS
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)
# END OF CLASS

Not being a Django expert, I wanted to ask whether this is okay
security-wise? Any other feedback is of course welcome.

Best,
Kaspar

P.S. I opened a question at stackoverflow,

  
http://stackoverflow.com/questions/7901895/how-to-install-a-custom-upload-handler-in-a-django-generic-view

and will keep both this thread and the latter post updated.

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to