如何在 Django 通用视图中安装自定义上传处理程序?

发布于 2024-12-12 03:55:20 字数 3271 浏览 0 评论 0原文

为了提供文件上传的进度反馈,我需要为特定视图安装自定义上传处理程序。这是关于“经典”Django 视图的文档,位于

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

对于 通用视图,但是,我找不到任何说明,我想出了以下内容:

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)

这是完成任务的“推荐方式”吗?安全方面还好吗?

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

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:

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'^.../

Is this the "recommended way" to accomplish the task? Is it okay security-wise?

, 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)

Is this the "recommended way" to accomplish the task? Is it okay security-wise?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

后eg是否自 2024-12-19 03:55:20

回答我自己,服务端解决方案(例如具有自定义上传处理程序的 Django)的替代方案是客户端解决方案,例如 JQuery 文件上传。它利用了以下事实:较新的浏览器允许在客户端上读取上传进度。就我而言,这实现起来要简单得多,并且不会导致额外的服务器负载。

Answering myself, an alternative to a service-side solution (like Django with a custom upload handler) is a client-side solution like JQuery File Upload. It uses the fact that more recent browsers allow the upload progress to be read on the client. In my case, this was much simpler to implement and causes no additional server load.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文