add a sendfile class based view implementation

pull/2583/merge
Yannick Chabbert 2016-04-07 15:07:49 +02:00 zatwierdzone przez Karl Hobley
rodzic 4ae735fae2
commit 58dfea096e
6 zmienionych plików z 111 dodań i 2 usunięć

Wyświetl plik

@ -97,3 +97,52 @@ method in your urls configuration:
url(r'^images/([^/]*)/(\d*)/([^/]*)/[^/]*$', ServeView.as_view(action='redirect'), name='wagtailimages_serve'),
]
Integration with django-sendfile
--------------------------------
`django-sendfile`_ offloads the job of transferring the image data to the web
server instead of serving it directly from the Django application. This could
greatly reduce server load in situations where your site has many images being
downloaded but you're unable to use a :ref:`caching_proxy` or a CDN.
.. _django-sendfile: https://github.com/johnsensible/django-sendfile
You firstly need to install and configure django-sendfile and configure your
web server to use it. If you haven't done this already, please refer to the
`installation docs <https://github.com/johnsensible/django-sendfile#django-sendfile>`_.
To serve images with django-sendfile, you can use the ``SendFileView`` class.
This view can be used out of the box:
.. code-block:: python
from wagtail.wagtailimages.views.serve import SendFileView
urlpatterns = [
...
url(r'^images/([^/]*)/(\d*)/([^/]*)/[^/]*$', SendFileView.as_view(), name='wagtailimages_serve'),
]
You can customise it to override the backend defined in the ``SENDFILE_BACKEND``
setting:
.. code-block:: python
from wagtail.wagtailimages.views.serve import SendFileView
from project.sendfile_backends import MyCustomBackend
class MySendFileView(SendFileView):
backend = MyCustomBackend
You can also customise it to serve private files. For example, if the only need
is to be authenticated (e.g. for Django >= 1.9):
.. code-block:: python
from django.contrib.auth.mixins import LoginRequiredMixin
from wagtail.wagtailimages.views.serve import SendFileView
class PrivateSendFileView(LoginRequiredMixin, SendFileView):
raise_exception = True

Wyświetl plik

@ -58,6 +58,8 @@ Wagtail is tested on SQLite, and should work on other Django-supported database
Public users
~~~~~~~~~~~~
.. _caching_proxy:
Caching proxy
-------------

Wyświetl plik

@ -0,0 +1,10 @@
from __future__ import absolute_import, unicode_literals
from django.http import HttpResponse
def sendfile(request, filename, **kwargs):
"""
Dummy sendfile backend implementation.
"""
return HttpResponse('Dummy backend response')

Wyświetl plik

@ -1,11 +1,12 @@
from __future__ import absolute_import, unicode_literals
import os
import unittest
from django import forms, template
from django.core.exceptions import ImproperlyConfigured
from django.core.urlresolvers import reverse
from django.test import TestCase
from django.test import TestCase, override_settings
from django.utils import six
from mock import MagicMock
from taggit.forms import TagField, TagWidget
@ -21,6 +22,12 @@ from wagtail.wagtailimages.views.serve import ServeView, generate_signature, ver
from .utils import Image, get_test_image_file
try:
import sendfile # noqa
sendfile_mod = True
except:
sendfile_mod = False
class TestImageTag(TestCase):
def setUp(self):
@ -354,6 +361,36 @@ class TestFrontendServeView(TestCase):
self.assertEqual(response.status_code, 410)
class TestFrontendSendfileView(TestCase):
def setUp(self):
self.image = Image.objects.create(
title="Test image",
file=get_test_image_file(),
)
@override_settings(SENDFILE_BACKEND='sendfile.backends.development')
@unittest.skipIf(not sendfile_mod, 'Missing django-sendfile app.')
def test_sendfile_nobackend(self):
signature = generate_signature(self.image.id, 'fill-800x600')
response = self.client.get(reverse('wagtailimages_sendfile',
args=(signature, self.image.id,
'fill-800x600')))
self.assertEqual(response.status_code, 200)
self.assertEqual(response['Content-Type'], 'image/png')
@override_settings(SENDFILE_BACKEND='sendfile.backends.development')
def test_sendfile_dummy_backend(self):
signature = generate_signature(self.image.id, 'fill-800x600')
response = self.client.get(reverse('wagtailimages_sendfile_dummy',
args=(signature, self.image.id,
'fill-800x600')))
self.assertEqual(response.status_code, 200)
self.assertTrue(response.content, 'Dummy backend response')
class TestRect(TestCase):
def test_init(self):
rect = Rect(100, 150, 200, 250)

Wyświetl plik

@ -2,10 +2,13 @@ from __future__ import absolute_import, unicode_literals
from django.conf.urls import url
from wagtail.wagtailimages.views.serve import ServeView
from wagtail.tests import dummy_sendfile_backend
from wagtail.wagtailimages.views.serve import SendFileView, ServeView
urlpatterns = [
url(r'^actions/serve/(.*)/(\d*)/(.*)/[^/]*', ServeView.as_view(action='serve'), name='wagtailimages_serve_action_serve'),
url(r'^actions/redirect/(.*)/(\d*)/(.*)/[^/]*', ServeView.as_view(action='redirect'), name='wagtailimages_serve_action_redirect'),
url(r'^custom_key/(.*)/(\d*)/(.*)/[^/]*', ServeView.as_view(key='custom'), name='wagtailimages_serve_custom_key'),
url(r'^sendfile/(.*)/(\d*)/(.*)/[^/]*', SendFileView.as_view(), name='wagtailimages_sendfile'),
url(r'^sendfile-dummy/(.*)/(\d*)/(.*)/[^/]*', SendFileView.as_view(backend=dummy_sendfile_backend.sendfile), name='wagtailimages_sendfile_dummy'),
]

Wyświetl plik

@ -14,6 +14,7 @@ from django.utils.decorators import classonlymethod
from django.utils.six import text_type
from django.views.generic import View
from wagtail.utils.sendfile import sendfile
from wagtail.wagtailimages.exceptions import InvalidFilterSpecError
from wagtail.wagtailimages.models import SourceImageIOError, get_image_model
@ -78,3 +79,10 @@ class ServeView(View):
serve = ServeView.as_view()
class SendFileView(ServeView):
backend = None
def serve(self, rendition):
return sendfile(self.request, rendition.file.path, backend=self.backend)