Introduced ObjectDownloadView. UNSTABLE. Work in progress.

This commit is contained in:
Benoit Bryon 2012-08-27 17:05:24 +02:00
parent 224fbb15ec
commit a45c79552e
6 changed files with 68 additions and 14 deletions

View file

@ -0,0 +1,8 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
class Document(models.Model):
"""A sample model with a FileField."""
slug = models.SlugField(verbose_name=_('slug'))
file = models.FileField(verbose_name=_('file'), upload_to='document')

View file

@ -2,24 +2,32 @@
from os import listdir
from os.path import abspath, dirname, join
from django.core.urlresolvers import reverse
from django.core.files import File
from django.core.urlresolvers import reverse_lazy as reverse
from django.test import TestCase
from demoproject.download.models import Document
app_dir = dirname(abspath(__file__))
fixtures_dir = join(app_dir, 'fixtures')
class DownloadViewTestCase(TestCase):
"""Test generic DownloadView."""
class DownloadTestCase(TestCase):
"""Base class for download tests."""
def setUp(self):
"""Common setup."""
super(DownloadViewTestCase, self).setUp()
super(DownloadTestCase, self).setUp()
self.download_hello_world_url = reverse('download_hello_world')
self.download_document_url = reverse('download_document',
kwargs={'slug': 'hello-world'})
self.files = {}
for f in listdir(fixtures_dir):
self.files[f] = abspath(join(fixtures_dir, f))
class DownloadViewTestCase(DownloadTestCase):
"""Test generic DownloadView."""
def test_download_hello_world(self):
"""Download_hello_world view returns hello-world.txt as attachement."""
response = self.client.get(self.download_hello_world_url)
@ -29,3 +37,20 @@ class DownloadViewTestCase(TestCase):
'attachment; filename=hello-world.txt')
self.assertEqual(open(self.files['hello-world.txt']).read(),
response.content)
class ObjectDownloadViewTestCase(DownloadTestCase):
"""Test generic ObjectDownloadView."""
def test_download_hello_world(self):
"""Download_hello_world view returns hello-world.txt as attachement."""
document = Document.objects.create(
slug='hello-world',
file=File(open(self.files['hello-world.txt'])),
)
response = self.client.get(self.download_document_url)
self.assertEquals(response.status_code, 200)
self.assertEquals(response['Content-Type'], 'application/octet-stream')
self.assertEquals(response['Content-Disposition'],
'attachment; filename=hello-world.txt')
self.assertEqual(open(self.files['hello-world.txt']).read(),
response.content)

View file

@ -3,6 +3,8 @@ from django.conf.urls import patterns, include, url
urlpatterns = patterns('demoproject.download.views',
url(r'^download/hello-world\.txt$', 'download_hello_world',
url(r'^hello-world\.txt$', 'download_hello_world',
name='download_hello_world'),
url(r'^document/(?P<slug>[a-zA-Z0-9_-]+)/$', 'download_document',
name='download_document'),
)

View file

@ -1,6 +1,8 @@
from os.path import abspath, dirname, join
from django_downloadview import DownloadView
from django_downloadview import DownloadView, ObjectDownloadView
from demoproject.download.models import Document
app_dir = dirname(abspath(__file__))
@ -9,3 +11,6 @@ hello_world_file = join(fixtures_dir, 'hello-world.txt')
download_hello_world = DownloadView.as_view(file=hello_world_file)
download_document = ObjectDownloadView.as_view(model=Document)

View file

@ -1,5 +1,5 @@
"""django-downloadview provides generic download views for Django."""
from django_downloadview.views import DownloadView
from django_downloadview.views import DownloadView, ObjectDownloadView
#: Implement :pep:`396`

View file

@ -1,23 +1,28 @@
from os.path import abspath, basename
import shutil
from django.core.files import File
from django.http import HttpResponse
from django.views.generic.base import View
from django.views.generic.detail import BaseDetailView
class DownloadMixin(object):
file = None
response_class = HttpResponse
def get_mime_type(self, file):
"""Return mime-type of file."""
def get_mime_type(self):
"""Return mime-type of self.file."""
return 'application/octet-stream'
def render_to_response(self, file, **response_kwargs):
def render_to_response(self, **response_kwargs):
"""Returns a response with a file as attachment."""
mime_type = self.get_mime_type(file)
absolute_filename = abspath(file)
filename = basename(file)
mime_type = self.get_mime_type()
if isinstance(self.file, File):
absolute_filename = self.file.name
else:
absolute_filename = abspath(self.file)
filename = basename(absolute_filename)
response = self.response_class(mimetype=mime_type)
# Open file as read binary.
with open(absolute_filename, 'rb') as f:
@ -30,4 +35,13 @@ class DownloadMixin(object):
class DownloadView(DownloadMixin, View):
def get(self, request, *args, **kwargs):
return self.render_to_response(self.file)
return self.render_to_response()
class ObjectDownloadView(DownloadMixin, BaseDetailView):
file_attribute = 'file'
def get(self, request, *args, **kwargs):
self.object = self.get_object()
self.file = getattr(self.object, self.file_attribute)
return self.render_to_response()