From 46542cdc3c80f2484991e2f523677fc2b0786261 Mon Sep 17 00:00:00 2001 From: Benoit Bryon Date: Mon, 19 Nov 2012 14:39:30 +0100 Subject: [PATCH] Refs #3 - Introduced base decorators and middlewares. --- django_downloadview/decorators.py | 27 +++++++++++++++++++++++++++ django_downloadview/middlewares.py | 22 ++++++++++++++++++++++ django_downloadview/response.py | 10 ++++++++++ docs/api/django_downloadview.txt | 24 ++++++++++++++++++++++++ 4 files changed, 83 insertions(+) create mode 100644 django_downloadview/decorators.py create mode 100644 django_downloadview/middlewares.py diff --git a/django_downloadview/decorators.py b/django_downloadview/decorators.py new file mode 100644 index 0000000..3e93ec3 --- /dev/null +++ b/django_downloadview/decorators.py @@ -0,0 +1,27 @@ +"""View decorators.""" + + +class DownloadDecorator(object): + """View decorator factory to apply middleware to ``view_func`` response. + + Middleware instance is built from ``middleware_factory`` with ``*args`` and + ``**kwargs``. Middleware factory is typically a class, such as some + :py:class:`django_downloadview.middlewares.XAccelMiddleware` subclass. + + Response is built from view, then the middleware's ``process_response`` + method is applied on response. + + """ + def __init__(self, middleware_factory): + """Create a download view decorator.""" + self.middleware_factory = middleware_factory + + def __call__(self, view_func, *middleware_args, **middleware_kwargs): + """Return ``view_func`` decorated with response middleware.""" + def decorated(request, *view_args, **view_kwargs): + """Return view's response modified by middleware.""" + response = view_func(request, *view_args, **view_kwargs) + middleware = self.middleware_factory(*middleware_args, + **middleware_kwargs) + return middleware.process_response(request, response) + return decorated diff --git a/django_downloadview/middlewares.py b/django_downloadview/middlewares.py new file mode 100644 index 0000000..d0c2cbb --- /dev/null +++ b/django_downloadview/middlewares.py @@ -0,0 +1,22 @@ +"""Base material for download middlewares.""" +from django_downloadview.response import is_download_response + + +class BaseDownloadMiddleware(object): + """Base (abstract) Django middleware that process download responses. + + Subclasses **must** implement ``process_download_response`` method. + + """ + def is_download_response(self, response): + """Return True if ``response`` can be considered as a file download.""" + return is_download_response(response) + + def process_response(self, request, response): + """Call ``process_download_response()`` if ``response`` is download.""" + if self.is_download_response(response): + return self.process_download_response(request, response) + + def process_download_response(self, request, response): + """Handle file download response.""" + raise NotImplementedError() diff --git a/django_downloadview/response.py b/django_downloadview/response.py index 592f41d..9f6c2c5 100644 --- a/django_downloadview/response.py +++ b/django_downloadview/response.py @@ -50,3 +50,13 @@ class DownloadResponse(HttpResponse): if expires: self['Expires'] = expires self['Content-Disposition'] = 'attachment; filename=%s' % basename + + +def is_download_response(response): + """Return ``True`` if ``response`` is a download response. + + Current implementation returns True if ``response`` is an instance of + :py:class:`django_downloadview.DownloadResponse`. + + """ + return isinstance(response, DownloadResponse) diff --git a/docs/api/django_downloadview.txt b/docs/api/django_downloadview.txt index a6255ec..4b70ab3 100644 --- a/docs/api/django_downloadview.txt +++ b/docs/api/django_downloadview.txt @@ -9,6 +9,30 @@ django_downloadview Package :undoc-members: :show-inheritance: +:mod:`decorators` Module +------------------------ + +.. automodule:: django_downloadview.decorators + :members: + :undoc-members: + :show-inheritance: + +:mod:`middlewares` Module +------------------------- + +.. automodule:: django_downloadview.middlewares + :members: + :undoc-members: + :show-inheritance: + +:mod:`response` Module +---------------------- + +.. automodule:: django_downloadview.response + :members: + :undoc-members: + :show-inheritance: + :mod:`views` Module -------------------