Complete conversion of download views to CBV views using django-downloadview.

This also removes dependency on the filetransfers library.
This commit is contained in:
Roberto Rosario
2016-10-31 01:00:35 -04:00
parent 24ef702e9c
commit 6e3d99670c
37 changed files with 437 additions and 340 deletions

View File

@@ -5,7 +5,6 @@ import logging
from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404
from filetransfers.api import serve_file
from rest_framework import generics, status
from rest_framework.response import Response
@@ -87,7 +86,16 @@ class APIDeletedDocumentRestoreView(generics.GenericAPIView):
return Response(status=status.HTTP_200_OK)
class APIDocumentDownloadView(generics.RetrieveAPIView):
##############
from django_downloadview import VirtualDownloadView
from django_downloadview import VirtualFile
from django_downloadview import DownloadMixin
#class SingleObjectDownloadView(ViewPermissionCheckMixin, ObjectPermissionCheckMixin, VirtualDownloadView, SingleObjectMixin):
# VirtualFile = VirtualFile
class APIDocumentDownloadView(DownloadMixin, generics.RetrieveAPIView):
"""
Download the latest version of a document.
---
@@ -105,17 +113,15 @@ class APIDocumentDownloadView(generics.RetrieveAPIView):
permission_classes = (MayanPermission,)
queryset = Document.objects.all()
def get_file(self):
instance = self.get_object()
return VirtualFile(instance.latest_version.file, name=instance.label)
def get_serializer_class(self):
return None
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
return serve_file(
request,
instance.latest_version.file,
save_as='"%s"' % instance.label,
content_type=instance.latest_version.mimetype if instance.latest_version.mimetype else 'application/octet-stream'
)
return self.render_to_response()
class APIDocumentListView(generics.ListCreateAPIView):
@@ -146,7 +152,7 @@ class APIDocumentListView(generics.ListCreateAPIView):
return super(APIDocumentListView, self).post(*args, **kwargs)
class APIDocumentVersionDownloadView(generics.RetrieveAPIView):
class APIDocumentVersionDownloadView(DownloadMixin, generics.RetrieveAPIView):
"""
Download a document version.
---
@@ -164,17 +170,15 @@ class APIDocumentVersionDownloadView(generics.RetrieveAPIView):
permission_classes = (MayanPermission,)
queryset = DocumentVersion.objects.all()
def get_file(self):
instance = self.get_object()
return VirtualFile(instance.file, name=unicode(instance))
def get_serializer_class(self):
return None
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
return serve_file(
request,
instance.file,
save_as='"%s"' % instance.document.label,
content_type=instance.mimetype if instance.mimetype else 'application/octet-stream'
)
return self.render_to_response()
class APIDocumentView(generics.RetrieveUpdateDestroyAPIView):

View File

@@ -66,7 +66,8 @@ from .permissions import (
permission_document_trash, permission_document_version_revert,
permission_document_view
)
from .search import document_search, document_page_search
# Just import to initialize the search models
from .search import document_search, document_page_search # NOQA
from .settings import setting_thumbnail_size
from .statistics import (
new_documents_per_month, new_document_pages_per_month,

View File

@@ -85,7 +85,7 @@ link_document_document_type_edit = Link(
)
link_document_download = Link(
permissions=(permission_document_download,), text=_('Download'),
view='documents:document_download', args='resolved_object.id'
view='documents:document_download_form', args='resolved_object.id'
)
link_document_print = Link(
permissions=(permission_document_print,), text=_('Print'),
@@ -118,7 +118,7 @@ link_document_multiple_document_type_edit = Link(
view='documents:document_multiple_document_type_edit'
)
link_document_multiple_download = Link(
text=_('Download'), view='documents:document_multiple_download'
text=_('Download'), view='documents:document_multiple_download_form'
)
link_document_multiple_update_page_count = Link(
text=_('Recalculate page count'),
@@ -129,7 +129,7 @@ link_document_multiple_restore = Link(
)
link_document_version_download = Link(
args='resolved_object.pk', permissions=(permission_document_download,),
text=_('Download version'), view='documents:document_version_download'
text=_('Download version'), view='documents:document_version_download_form'
)
# Views

View File

@@ -46,11 +46,14 @@ from .signals import (
post_document_created, post_document_type_change, post_version_upload
)
# document image cache name hash function
HASH_FUNCTION = lambda x: hashlib.sha256(x).hexdigest()
logger = logging.getLogger(__name__)
# document image cache name hash function
def HASH_FUNCTION(data):
return hashlib.sha256(data).hexdigest()
def UUID_FUNCTION(*args, **kwargs):
return unicode(uuid.uuid4())

View File

@@ -7,11 +7,11 @@ import time
from json import loads
from django.contrib.auth import get_user_model
from django.core.urlresolvers import reverse
from django.test import override_settings
from django.utils.six import BytesIO
from django_downloadview import assert_download_response
from rest_framework import status
from rest_framework.test import APITestCase
@@ -21,7 +21,7 @@ from user_management.tests.literals import (
from .literals import (
TEST_DOCUMENT_FILENAME, TEST_DOCUMENT_PATH, TEST_DOCUMENT_TYPE,
TEST_SMALL_DOCUMENT_CHECKSUM, TEST_SMALL_DOCUMENT_PATH,
TEST_SMALL_DOCUMENT_FILENAME, TEST_SMALL_DOCUMENT_PATH,
)
from ..models import Document, DocumentType, HASH_FUNCTION
@@ -263,14 +263,13 @@ class DocumentAPITestCase(APITestCase):
'rest_api:document-download', args=(document.pk,)
)
)
buf = BytesIO()
buf.write(response.content)
self.assertEqual(
HASH_FUNCTION(buf.getvalue()), TEST_SMALL_DOCUMENT_CHECKSUM
)
del(buf)
with document.open() as file_object:
assert_download_response(
self, response, content=file_object.read(),
basename=TEST_SMALL_DOCUMENT_FILENAME,
mime_type='{}; charset=utf-8'.format(document.file_mimetype)
)
def test_document_version_download(self):
with open(TEST_SMALL_DOCUMENT_PATH) as file_object:
@@ -278,20 +277,22 @@ class DocumentAPITestCase(APITestCase):
file_object=file_object,
)
latest_version = document.latest_version
response = self.client.get(
reverse(
'rest_api:documentversion-download',
args=(document.latest_version.pk,)
args=(latest_version.pk,)
)
)
buf = BytesIO()
buf.write(response.content)
self.assertEqual(
HASH_FUNCTION(buf.getvalue()), TEST_SMALL_DOCUMENT_CHECKSUM
)
del(buf)
with latest_version.open() as file_object:
assert_download_response(
self, response, content=file_object.read(),
basename='{} - {}'.format(
TEST_SMALL_DOCUMENT_FILENAME,
latest_version.timestamp
), mime_type='application/octet-stream; charset=utf-8'
)
# TODO: def test_document_set_document_type(self):
# pass

View File

@@ -3,8 +3,8 @@
from __future__ import unicode_literals
from actstream.models import Action
from django_downloadview import assert_download_response
from common.tests import skip_file_descriptor_check
from user_management.tests.literals import (
TEST_USER_PASSWORD, TEST_USER_USERNAME
)
@@ -14,7 +14,6 @@ from ..permissions import (
permission_document_download, permission_document_view
)
from .test_views import GenericDocumentViewTestCase
@@ -32,17 +31,14 @@ class DocumentEventsTestCase(GenericDocumentViewTestCase):
Action.objects.all().delete()
response = self.post(
response = self.get(
'documents:document_download', args=(self.document.pk,)
)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 403)
self.assertEqual(list(Action.objects.any(obj=self.document)), [])
@skip_file_descriptor_check
def test_document_download_event_with_permissions(self):
# TODO: Skip this test's file descriptor check until it gets migrate
# SingleObjectDownloadView CBV
self.login(
username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD
)
@@ -53,12 +49,19 @@ class DocumentEventsTestCase(GenericDocumentViewTestCase):
permission_document_download.stored_permission
)
self.expected_content_type = 'image/png'
self.expected_content_type = 'image/png; charset=utf-8'
self.post(
response = self.get(
'documents:document_download', args=(self.document.pk,),
)
# Download the file to close the file descriptor
with self.document.open() as file_object:
assert_download_response(
self, response, content=file_object.read(),
mime_type=self.document.file_mimetype
)
event = Action.objects.any(obj=self.document).first()
self.assertEqual(event.verb, event_document_download.name)

View File

@@ -94,7 +94,7 @@ class DocumentsLinksTestCase(GenericDocumentViewTestCase):
self.assertEqual(
resolved_link.url,
reverse(
'documents:document_version_download',
'documents:document_version_download_form',
args=(self.document.latest_version.pk,)
)
)

View File

@@ -4,7 +4,7 @@ from datetime import timedelta
import time
from common.tests import BaseTestCase
from django.test import TestCase, override_settings
from django.test import override_settings
from ..exceptions import NewDocumentVersionNotAllowed
from ..literals import STUB_EXPIRATION_INTERVAL

View File

@@ -4,9 +4,9 @@ from __future__ import unicode_literals
from django.contrib.contenttypes.models import ContentType
from django.test import override_settings
from django.utils.six import BytesIO
from common.tests import skip_file_descriptor_check
from django_downloadview import assert_download_response
from common.tests.test_views import GenericViewTestCase
from converter.models import Transformation
from converter.permissions import permission_transformation_delete
@@ -15,9 +15,7 @@ from user_management.tests.literals import (
)
from ..literals import DEFAULT_DELETE_PERIOD, DEFAULT_DELETE_TIME_UNIT
from ..models import (
DeletedDocument, Document, DocumentType, HASH_FUNCTION
)
from ..models import DeletedDocument, Document, DocumentType
from ..permissions import (
permission_document_create, permission_document_delete,
permission_document_download, permission_document_properties_edit,
@@ -30,7 +28,7 @@ from ..permissions import (
from .literals import (
TEST_DOCUMENT_TYPE, TEST_DOCUMENT_TYPE_QUICK_LABEL,
TEST_SMALL_DOCUMENT_CHECKSUM, TEST_SMALL_DOCUMENT_PATH
TEST_SMALL_DOCUMENT_FILENAME, TEST_SMALL_DOCUMENT_PATH
)
@@ -226,113 +224,113 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
Document.objects.first().document_type, document_type
)
@skip_file_descriptor_check
def test_document_download_user_view(self):
# TODO: Skip this test's file descriptor check until it gets migrate
# SingleObjectDownloadView CBV
def test_document_download_view_no_permission(self):
self.login(
username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD
)
self.assertEqual(Document.objects.count(), 1)
response = self.post(
response = self.get(
'documents:document_download', args=(self.document.pk,)
)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 403)
def test_document_download_view_with_permission(self):
self.login(
username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD
)
self.role.permissions.add(
permission_document_download.stored_permission
)
# Set the expected_content_type for common.tests.mixins.ContentTypeCheckMixin
self.expected_content_type = self.document.file_mimetype
# Set the expected_content_type for
# common.tests.mixins.ContentTypeCheckMixin
self.expected_content_type = '{}; charset=utf-8'.format(
self.document.file_mimetype
)
response = self.post(
response = self.get(
'documents:document_download', args=(self.document.pk,)
)
self.assertEqual(response.status_code, 200)
buf = BytesIO()
buf.write(response.content)
self.assertEqual(
HASH_FUNCTION(buf.getvalue()), TEST_SMALL_DOCUMENT_CHECKSUM
)
del(buf)
@skip_file_descriptor_check
def test_document_multiple_download_user_view(self):
# TODO: Skip this test's file descriptor check until it gets migrate
# SingleObjectDownloadView CBV
with self.document.open() as file_object:
assert_download_response(
self, response, content=file_object.read(),
basename=TEST_SMALL_DOCUMENT_FILENAME,
mime_type=self.document.file_mimetype
)
def test_document_multiple_download_view_no_permission(self):
self.login(
username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD
)
self.assertEqual(Document.objects.count(), 1)
response = self.post(
response = self.get(
'documents:document_multiple_download',
data={'id_list': self.document.pk}
)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 403)
def test_document_multiple_download_view_with_permission(self):
self.login(
username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD
)
self.role.permissions.add(
permission_document_download.stored_permission
)
# Set the expected_content_type for common.tests.mixins.ContentTypeCheckMixin
self.expected_content_type = self.document.file_mimetype
# Set the expected_content_type for
# common.tests.mixins.ContentTypeCheckMixin
self.expected_content_type = '{}; charset=utf-8'.format(
self.document.file_mimetype
)
response = self.post(
response = self.get(
'documents:document_multiple_download',
data={'id_list': self.document.pk}
)
self.assertEqual(response.status_code, 200)
buf = BytesIO()
buf.write(response.content)
self.assertEqual(
HASH_FUNCTION(buf.getvalue()), TEST_SMALL_DOCUMENT_CHECKSUM
)
del(buf)
@skip_file_descriptor_check
def test_document_version_download_user_view(self):
# TODO: Skip this test's file descriptor check until it gets migrate
# SingleObjectDownloadView CBV
with self.document.open() as file_object:
assert_download_response(
self, response, content=file_object.read(),
basename=TEST_SMALL_DOCUMENT_FILENAME,
mime_type=self.document.file_mimetype
)
def test_document_version_download_view_no_permission(self):
self.login(
username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD
)
self.assertEqual(Document.objects.count(), 1)
response = self.post(
response = self.get(
'documents:document_version_download', args=(
self.document.latest_version.pk,
)
)
self.assertEqual(response.status_code, 302)
self.assertEqual(response.status_code, 403)
def test_document_version_download_view_with_permission(self):
self.login(
username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD
)
self.role.permissions.add(
permission_document_download.stored_permission
)
# Set the expected_content_type for common.tests.mixins.ContentTypeCheckMixin
self.expected_content_type = self.document.file_mimetype
# Set the expected_content_type for
# common.tests.mixins.ContentTypeCheckMixin
self.expected_content_type = 'application/octet-stream; charset=utf-8'
response = self.post(
response = self.get(
'documents:document_version_download', args=(
self.document.latest_version.pk,
)
@@ -340,14 +338,14 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
self.assertEqual(response.status_code, 200)
buf = BytesIO()
buf.write(response.content)
self.assertEqual(
HASH_FUNCTION(buf.getvalue()), TEST_SMALL_DOCUMENT_CHECKSUM
)
del(buf)
with self.document.open() as file_object:
assert_download_response(
self, response, content=file_object.read(),
basename='{} - {}'.format(
TEST_SMALL_DOCUMENT_FILENAME,
self.document.latest_version.timestamp
), mime_type='application/octet-stream; charset=utf-8'
)
def test_document_update_page_count_view_no_permission(self):
self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD)
@@ -380,7 +378,6 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
self.assertContains(response, text='queued', status_code=200)
self.assertEqual(self.document.pages.count(), page_count)
def test_document_multiple_update_page_count_view_no_permission(self):
self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD)

View File

@@ -15,7 +15,8 @@ from .api_views import (
from .settings import setting_print_size, setting_display_size
from .views import (
ClearImageCacheView, DeletedDocumentDeleteView,
DeletedDocumentDeleteManyView, DeletedDocumentListView, DocumentEditView,
DeletedDocumentDeleteManyView, DeletedDocumentListView,
DocumentDownloadFormView, DocumentDownloadView, DocumentEditView,
DocumentListView, DocumentPageView, DocumentPageListView,
DocumentPageViewResetView, DocumentPreviewView, DocumentRestoreView,
DocumentRestoreManyView, DocumentTrashView, DocumentTrashManyView,
@@ -23,6 +24,7 @@ from .views import (
DocumentTypeDocumentListView, DocumentTypeFilenameCreateView,
DocumentTypeFilenameDeleteView, DocumentTypeFilenameEditView,
DocumentTypeFilenameListView, DocumentTypeListView, DocumentTypeEditView,
DocumentVersionDownloadFormView, DocumentVersionDownloadView,
DocumentVersionListView, DocumentVersionRevertView, DocumentView,
EmptyTrashCanView, RecentDocumentListView
)
@@ -107,13 +109,20 @@ urlpatterns = patterns(
'size': setting_print_size.value
}, 'document_display_print'
),
url(
r'^(?P<document_id>\d+)/download/$', 'document_download',
r'^(?P<pk>\d+)/download/form/$',
DocumentDownloadFormView.as_view(), name='document_download_form'
),
url(
r'^(?P<pk>\d+)/download/$', DocumentDownloadView.as_view(),
name='document_download'
),
url(
r'^multiple/download/$', 'document_multiple_download',
r'^multiple/download/form/$', DocumentDownloadFormView.as_view(),
name='document_multiple_download_form'
),
url(
r'^multiple/download/$', DocumentDownloadView.as_view(),
name='document_multiple_download'
),
url(
@@ -127,8 +136,13 @@ urlpatterns = patterns(
name='document_version_list'
),
url(
r'^document/version/(?P<document_version_pk>\d+)/download/$',
'document_download', name='document_version_download'
r'^document/version/(?P<pk>\d+)/download/form/$',
DocumentVersionDownloadFormView.as_view(),
name='document_version_download_form'
),
url(
r'^document/version/(?P<pk>\d+)/download/$',
DocumentVersionDownloadView.as_view(), name='document_version_download'
),
url(
r'^document/version/(?P<pk>\d+)/revert/$',

View File

@@ -18,8 +18,9 @@ from django.views.generic import RedirectView
from acls.models import AccessControlList
from common.compressed_files import CompressedFile
from common.generics import (
ConfirmView, SimpleView, SingleObjectCreateView, SingleObjectDeleteView,
SingleObjectDetailView, SingleObjectEditView, SingleObjectListView
ConfirmView, FormView, SimpleView, SingleObjectCreateView,
SingleObjectDeleteView, SingleObjectDetailView, SingleObjectDownloadView,
SingleObjectEditView, SingleObjectListView
)
from common.mixins import MultipleInstanceActionMixin
from converter.literals import (
@@ -27,7 +28,6 @@ from converter.literals import (
)
from converter.models import Transformation
from converter.permissions import permission_transformation_delete
from filetransfers.api import serve_file
from permissions import Permission
from .events import event_document_download, event_document_view
@@ -36,7 +36,9 @@ from .forms import (
DocumentPropertiesForm, DocumentTypeSelectForm,
DocumentTypeFilenameForm_create, PrintForm
)
from .literals import DOCUMENT_IMAGE_TASK_TIMEOUT, PAGE_RANGE_RANGE
from .literals import (
DOCUMENT_IMAGE_TASK_TIMEOUT, PAGE_RANGE_RANGE, DEFAULT_ZIP_FILENAME
)
from .models import (
DeletedDocument, Document, DocumentType, DocumentPage,
DocumentTypeFilename, DocumentVersion, RecentDocument
@@ -771,154 +773,209 @@ def get_document_image(request, document_id, size=setting_preview_size.value):
return HttpResponse(base64.b64decode(data.partition('base64,')[2]), content_type='image')
def document_download(request, document_id=None, document_id_list=None, document_version_pk=None):
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL))))
class DocumentDownloadFormView(FormView):
form_class = DocumentDownloadForm
model = Document
multiple_download_view = 'documents:document_multiple_download'
single_download_view = 'documents:document_download'
if document_id:
documents = Document.objects.filter(pk=document_id)
elif document_id_list:
documents = Document.objects.filter(pk__in=document_id_list)
elif document_version_pk:
documents = Document.objects.filter(
pk=get_object_or_404(
DocumentVersion, pk=document_version_pk
).document.pk
def get_document_queryset(self):
id_list = self.request.GET.get(
'id_list', self.request.POST.get('id_list', '')
)
try:
Permission.check_permissions(
request.user, (permission_document_download,)
)
except PermissionDenied:
documents = AccessControlList.objects.filter_by_access(
permission_document_download, request.user, documents
)
if not id_list:
id_list = self.kwargs['pk']
if not documents:
messages.error(
request, _('Must provide at least one document or version.')
)
return HttpResponseRedirect(
request.META.get(
'HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)
)
)
return self.model.objects.filter(
pk__in=id_list.split(',')
).filter(is_stub=False)
if document_version_pk:
queryset = DocumentVersion.objects.filter(pk=document_version_pk)
else:
queryset = DocumentVersion.objects.filter(
pk__in=[document.latest_version.pk for document in documents]
)
subtemplates_list = []
subtemplates_list.append(
{
'name': 'appearance/generic_list_subtemplate.html',
'context': {
'title': _('Documents to be downloaded'),
'object_list': queryset,
'hide_link': True,
'hide_object': True,
'hide_links': True,
'scrollable_content': True,
'scrollable_content_height': '200px',
'extra_columns': (
{'name': _('Document'), 'attribute': 'document'},
{'name': _('Date and time'), 'attribute': 'timestamp'},
{'name': _('MIME type'), 'attribute': 'mimetype'},
{'name': _('Encoding'), 'attribute': 'encoding'},
),
def get_extra_context(self):
subtemplates_list = [
{
'name': 'appearance/generic_list_subtemplate.html',
'context': {
'object_list': self.queryset,
'hide_link': True,
'hide_links': True,
'hide_multi_item_actions': True,
}
}
]
context = {
'submit_label': _('Download'),
'subtemplates_list': subtemplates_list,
'title': _('Download documents'),
}
)
if request.method == 'POST':
form = DocumentDownloadForm(request.POST, queryset=queryset)
if form.is_valid():
if form.cleaned_data['compressed'] or queryset.count() > 1:
try:
compressed_file = CompressedFile()
for document_version in queryset:
descriptor = document_version.open()
compressed_file.add_file(
descriptor,
arcname=document_version.document.label
)
descriptor.close()
event_document_download.commit(
actor=request.user,
target=document_version.document
)
if self.queryset.count() == 1:
context['object'] = self.queryset.first()
compressed_file.close()
return context
return serve_file(
request,
compressed_file.as_file(
form.cleaned_data['zip_filename']
),
save_as='"%s"' % form.cleaned_data['zip_filename'],
content_type='application/zip'
)
except Exception as exception:
if settings.DEBUG:
raise
else:
messages.error(request, exception)
return HttpResponseRedirect(
request.META['HTTP_REFERER']
)
def get_form_kwargs(self):
kwargs = super(DocumentDownloadFormView, self).get_form_kwargs()
self.queryset = self.get_queryset()
kwargs.update({'queryset': self.queryset})
return kwargs
def form_valid(self, form):
querystring = urlencode(
{
'compressed': form.cleaned_data['compressed'],
'zip_filename': form.cleaned_data['zip_filename'],
'id_list': ','.join(
map(str, self.queryset.values_list('pk', flat=True))
)
}, doseq=True
)
if self.queryset.count() > 1:
url = reverse(self.multiple_download_view)
else:
url = reverse(
self.single_download_view, args=(self.queryset.first().pk,)
)
return HttpResponseRedirect('{}?{}'.format(url, querystring))
def get_post_action_redirect(self):
return self.post_action_redirect
def get_queryset(self):
queryset = self.get_document_queryset()
try:
Permission.check_permissions(
self.request.user, (permission_document_download,)
)
except PermissionDenied:
return AccessControlList.objects.filter_by_access(
permission_document_download, self.request.user, queryset
)
else:
return queryset
class DocumentDownloadView(SingleObjectDownloadView):
model = Document
# Set to None to disable the .get_object call
object_permission = None
@staticmethod
def commit_event(item, request):
if isinstance(item, Document):
event_document_download.commit(
actor=request.user,
target=item
)
else:
# TODO: Improve by adding a document version download event
event_document_download.commit(
actor=request.user,
target=item.document
)
@staticmethod
def get_item_file(item):
if isinstance(item, Document):
return item.open()
else:
return item.file
@staticmethod
def get_item_label(item):
if isinstance(item, Document):
return item.label
else:
return unicode(item)
def get_document_queryset(self):
id_list = self.request.GET.get(
'id_list', self.request.POST.get('id_list', '')
)
if not id_list:
id_list = self.kwargs['pk']
queryset = self.model.objects.filter(pk__in=id_list.split(','))
try:
Permission.check_permissions(
self.request.user, (permission_document_download,)
)
except PermissionDenied:
return AccessControlList.objects.filter_by_access(
permission_document_download, self.request.user, queryset
)
else:
return queryset
def get_file(self):
queryset = self.get_document_queryset()
zip_filename = self.request.GET.get(
'zip_filename', DEFAULT_ZIP_FILENAME
)
if self.request.GET.get('compressed') == 'True' or queryset.count() > 1:
compressed_file = CompressedFile()
for item in queryset:
descriptor = item.open()
compressed_file.add_file(
descriptor,
arcname=DocumentDownloadView.get_item_label(item=item)
)
descriptor.close()
DocumentDownloadView.commit_event(
item=item, request=self.request
)
compressed_file.close()
return DocumentDownloadView.VirtualFile(
compressed_file.as_file(zip_filename),
name=zip_filename
)
else:
item = queryset.first()
if item:
DocumentDownloadView.commit_event(
item=item, request=self.request
)
else:
try:
# Test permissions and trigger exception
fd = queryset.first().open()
fd.close()
event_document_download.commit(
actor=request.user, target=queryset.first().document
)
return serve_file(
request,
queryset.first().file,
save_as='"%s"' % queryset.first().document.label,
content_type=queryset.first().mimetype if queryset.first().mimetype else 'application/octet-stream'
)
except Exception as exception:
if settings.DEBUG:
raise
else:
messages.error(request, exception)
return HttpResponseRedirect(
request.META['HTTP_REFERER']
)
raise PermissionDenied
else:
form = DocumentDownloadForm(queryset=queryset)
context = {
'form': form,
'previous': previous,
'submit_label': _('Download'),
'subtemplates_list': subtemplates_list,
'title': _('Download documents'),
}
if queryset.count() == 1:
context['object'] = queryset.first().document
return render_to_response(
'appearance/generic_form.html',
context,
context_instance=RequestContext(request)
)
return DocumentDownloadView.VirtualFile(
DocumentDownloadView.get_item_file(item=item),
name=DocumentDownloadView.get_item_label(
item=item
)
)
def document_multiple_download(request):
return document_download(
request, document_id_list=request.GET.get(
'id_list', request.POST.get('id_list', '')
).split(',')
)
class DocumentVersionDownloadFormView(DocumentDownloadFormView):
model = DocumentVersion
multiple_download_view = None
single_download_view = 'documents:document_version_download'
def get_document_queryset(self):
id_list = self.request.GET.get(
'id_list', self.request.POST.get('id_list', '')
)
if not id_list:
id_list = self.kwargs['pk']
return self.model.objects.filter(
pk__in=id_list.split(',')
)
class DocumentVersionDownloadView(DocumentDownloadView):
model = DocumentVersion
object_permission = permission_document_download
def document_update_page_count(request, document_id=None, document_id_list=None):