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
+1
View File
@@ -3,6 +3,7 @@
- Remove the installation app - Remove the installation app
- Add support for document page search - Add support for document page search
- Remove recent searches feature - Remove recent searches feature
- Remove dependency on the django-filetransfer library
2.1.4 (2016-10-28) 2.1.4 (2016-10-28)
================== ==================
+2
View File
@@ -13,6 +13,7 @@ Other changes
- Remove the installation app - Remove the installation app
- Add support for page search - Add support for page search
- Remove recent searches feature - Remove recent searches feature
- Remove dependency on the django-filetransfer library
Removals Removals
-------- --------
@@ -43,6 +44,7 @@ existing installation.
Next upgrade/add the new requirements:: Next upgrade/add the new requirements::
$ pip uninstall -y django-filetransfers
$ pip install --upgrade -r requirements.txt $ pip install --upgrade -r requirements.txt
Common steps Common steps
+3 -1
View File
@@ -10,7 +10,9 @@ from .permissions import permission_acl_view, permission_acl_edit
def get_kwargs_factory(variable_name): def get_kwargs_factory(variable_name):
def get_kwargs(context): def get_kwargs(context):
ContentType = apps.get_model(app_label='django', model_name='ContentType') ContentType = apps.get_model(
app_label='contenttypes', model_name='ContentType'
)
content_type = ContentType.objects.get_for_model( content_type = ContentType.objects.get_for_model(
context[variable_name] context[variable_name]
@@ -23,7 +23,9 @@
<form action="{% url 'common:multi_object_action_view' %}" class="pure-form" method="get"> <form action="{% url 'common:multi_object_action_view' %}" class="pure-form" method="get">
{% if object_list %} {% if object_list %}
{% get_multi_item_links_form object_list %} {% if not hide_multi_item_actions %}
{% get_multi_item_links_form object_list %}
{% endif %}
{% if multi_item_actions %} {% if multi_item_actions %}
<fieldset> <fieldset>
{{ multi_item_form }} {{ multi_item_form }}
-30
View File
@@ -482,36 +482,6 @@ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
''') ''')
Package(label='django-filetransfers', license_text='''
Copyright (c) Waldemar Kornewald, Thomas Wanschik, and all contributors.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of All Buttons Pressed nor
the names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
''')
Package(label='django-pure-pagination', license_text=''' Package(label='django-pure-pagination', license_text='''
Copyright (c) James Pacileo and contributors. Copyright (c) James Pacileo and contributors.
All rights reserved. All rights reserved.
+1 -1
View File
@@ -3,7 +3,7 @@ from __future__ import unicode_literals
import zipfile import zipfile
try: try:
import zlib import zlib # NOQA
COMPRESSION = zipfile.ZIP_DEFLATED COMPRESSION = zipfile.ZIP_DEFLATED
except: except:
COMPRESSION = zipfile.ZIP_STORED COMPRESSION = zipfile.ZIP_STORED
+1 -2
View File
@@ -14,8 +14,7 @@ from django.views.generic.edit import (
) )
from django.views.generic.list import ListView from django.views.generic.list import ListView
from django_downloadview import VirtualDownloadView from django_downloadview import VirtualDownloadView, VirtualFile
from django_downloadview import VirtualFile
from pure_pagination.mixins import PaginationMixin from pure_pagination.mixins import PaginationMixin
from .forms import ChoiceForm from .forms import ChoiceForm
@@ -12,9 +12,16 @@ class Command(management.BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
management.call_command('createsettings', interactive=False) management.call_command('createsettings', interactive=False)
try: try:
result = management.call_command('migrate', interactive=False) management.call_command('migrate', interactive=False)
except OperationalError as exception: except OperationalError:
self.stderr.write(self.style.NOTICE('Unable to migrate the database. The initialsetup command is to be used only on new installations. To upgrade existing installations use the performupgrade command.')) self.stderr.write(
self.style.NOTICE(
'Unable to migrate the database. The initialsetup '
'command is to be used only on new installations. To '
'upgrade existing installations use the performupgrade '
'command.'
)
)
raise raise
management.call_command('createautoadmin', interactive=False) management.call_command('createautoadmin', interactive=False)
post_initial_setup.send(sender=self) post_initial_setup.send(sender=self)
+6 -6
View File
@@ -159,12 +159,6 @@ class RedirectionMixin(object):
post_action_redirect = None post_action_redirect = None
action_cancel_redirect = None action_cancel_redirect = None
def get_post_action_redirect(self):
return self.post_action_redirect
def get_action_cancel_redirect(self):
return self.action_cancel_redirect
def dispatch(self, request, *args, **kwargs): def dispatch(self, request, *args, **kwargs):
post_action_redirect = self.get_post_action_redirect() post_action_redirect = self.get_post_action_redirect()
action_cancel_redirect = self.get_action_cancel_redirect() action_cancel_redirect = self.get_action_cancel_redirect()
@@ -188,6 +182,9 @@ class RedirectionMixin(object):
RedirectionMixin, self RedirectionMixin, self
).dispatch(request, *args, **kwargs) ).dispatch(request, *args, **kwargs)
def get_action_cancel_redirect(self):
return self.action_cancel_redirect
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(RedirectionMixin, self).get_context_data(**kwargs) context = super(RedirectionMixin, self).get_context_data(**kwargs)
context.update( context.update(
@@ -199,6 +196,9 @@ class RedirectionMixin(object):
return context return context
def get_post_action_redirect(self):
return self.post_action_redirect
def get_success_url(self): def get_success_url(self):
return self.next_url or self.previous_url return self.next_url or self.previous_url
+4 -4
View File
@@ -1,5 +1,5 @@
def skip_file_descriptor_check(func): def skip_file_descriptor_check(func):
def func_wrapper(item): def func_wrapper(item):
item._skip_file_descriptor_test = True item._skip_file_descriptor_test = True
return func(item) return func(item)
return func_wrapper return func_wrapper
+1 -1
View File
@@ -66,7 +66,7 @@ class TempfileCheckMixin(object):
msg='Orphan temporary file. The number of temporary files and/or ' msg='Orphan temporary file. The number of temporary files and/or '
'directories at the start and at the end of the test are not the ' 'directories at the start and at the end of the test are not the '
'same. Orphan entries: {}'.format( 'same. Orphan entries: {}'.format(
','.join(final_temporary_items-self._temporary_items) ','.join(final_temporary_items - self._temporary_items)
) )
) )
super(TempfileCheckMixin, self).tearDown() super(TempfileCheckMixin, self).tearDown()
-1
View File
@@ -6,7 +6,6 @@ from django.contrib.auth.models import Group
from django.core.urlresolvers import clear_url_caches, reverse from django.core.urlresolvers import clear_url_caches, reverse
from django.http import HttpResponse from django.http import HttpResponse
from django.template import Context, Template from django.template import Context, Template
from django.test import TestCase
from permissions import Permission from permissions import Permission
from permissions.models import Role from permissions.models import Role
+3 -1
View File
@@ -13,7 +13,9 @@ from .permissions import (
def get_kwargs_factory(variable_name): def get_kwargs_factory(variable_name):
def get_kwargs(context): def get_kwargs(context):
ContentType = apps.get_model(app_label='django', model_name='ContentType') ContentType = apps.get_model(
app_label='contenttypes', model_name='ContentType'
)
content_type = ContentType.objects.get_for_model( content_type = ContentType.objects.get_for_model(
context[variable_name] context[variable_name]
+21 -17
View File
@@ -5,7 +5,6 @@ import logging
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from filetransfers.api import serve_file
from rest_framework import generics, status from rest_framework import generics, status
from rest_framework.response import Response from rest_framework.response import Response
@@ -87,7 +86,16 @@ class APIDeletedDocumentRestoreView(generics.GenericAPIView):
return Response(status=status.HTTP_200_OK) 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. Download the latest version of a document.
--- ---
@@ -105,17 +113,15 @@ class APIDocumentDownloadView(generics.RetrieveAPIView):
permission_classes = (MayanPermission,) permission_classes = (MayanPermission,)
queryset = Document.objects.all() 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): def get_serializer_class(self):
return None return None
def retrieve(self, request, *args, **kwargs): def retrieve(self, request, *args, **kwargs):
instance = self.get_object() return self.render_to_response()
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'
)
class APIDocumentListView(generics.ListCreateAPIView): class APIDocumentListView(generics.ListCreateAPIView):
@@ -146,7 +152,7 @@ class APIDocumentListView(generics.ListCreateAPIView):
return super(APIDocumentListView, self).post(*args, **kwargs) return super(APIDocumentListView, self).post(*args, **kwargs)
class APIDocumentVersionDownloadView(generics.RetrieveAPIView): class APIDocumentVersionDownloadView(DownloadMixin, generics.RetrieveAPIView):
""" """
Download a document version. Download a document version.
--- ---
@@ -164,17 +170,15 @@ class APIDocumentVersionDownloadView(generics.RetrieveAPIView):
permission_classes = (MayanPermission,) permission_classes = (MayanPermission,)
queryset = DocumentVersion.objects.all() queryset = DocumentVersion.objects.all()
def get_file(self):
instance = self.get_object()
return VirtualFile(instance.file, name=unicode(instance))
def get_serializer_class(self): def get_serializer_class(self):
return None return None
def retrieve(self, request, *args, **kwargs): def retrieve(self, request, *args, **kwargs):
instance = self.get_object() return self.render_to_response()
return serve_file(
request,
instance.file,
save_as='"%s"' % instance.document.label,
content_type=instance.mimetype if instance.mimetype else 'application/octet-stream'
)
class APIDocumentView(generics.RetrieveUpdateDestroyAPIView): class APIDocumentView(generics.RetrieveUpdateDestroyAPIView):
+2 -1
View File
@@ -66,7 +66,8 @@ from .permissions import (
permission_document_trash, permission_document_version_revert, permission_document_trash, permission_document_version_revert,
permission_document_view 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 .settings import setting_thumbnail_size
from .statistics import ( from .statistics import (
new_documents_per_month, new_document_pages_per_month, new_documents_per_month, new_document_pages_per_month,
+3 -3
View File
@@ -85,7 +85,7 @@ link_document_document_type_edit = Link(
) )
link_document_download = Link( link_document_download = Link(
permissions=(permission_document_download,), text=_('Download'), 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( link_document_print = Link(
permissions=(permission_document_print,), text=_('Print'), permissions=(permission_document_print,), text=_('Print'),
@@ -118,7 +118,7 @@ link_document_multiple_document_type_edit = Link(
view='documents:document_multiple_document_type_edit' view='documents:document_multiple_document_type_edit'
) )
link_document_multiple_download = Link( 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( link_document_multiple_update_page_count = Link(
text=_('Recalculate page count'), text=_('Recalculate page count'),
@@ -129,7 +129,7 @@ link_document_multiple_restore = Link(
) )
link_document_version_download = Link( link_document_version_download = Link(
args='resolved_object.pk', permissions=(permission_document_download,), 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 # Views
+5 -2
View File
@@ -46,11 +46,14 @@ from .signals import (
post_document_created, post_document_type_change, post_version_upload 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__) logger = logging.getLogger(__name__)
# document image cache name hash function
def HASH_FUNCTION(data):
return hashlib.sha256(data).hexdigest()
def UUID_FUNCTION(*args, **kwargs): def UUID_FUNCTION(*args, **kwargs):
return unicode(uuid.uuid4()) return unicode(uuid.uuid4())
+18 -17
View File
@@ -7,11 +7,11 @@ import time
from json import loads from json import loads
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.test import override_settings from django.test import override_settings
from django.utils.six import BytesIO from django.utils.six import BytesIO
from django_downloadview import assert_download_response
from rest_framework import status from rest_framework import status
from rest_framework.test import APITestCase from rest_framework.test import APITestCase
@@ -21,7 +21,7 @@ from user_management.tests.literals import (
from .literals import ( from .literals import (
TEST_DOCUMENT_FILENAME, TEST_DOCUMENT_PATH, TEST_DOCUMENT_TYPE, 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 from ..models import Document, DocumentType, HASH_FUNCTION
@@ -263,14 +263,13 @@ class DocumentAPITestCase(APITestCase):
'rest_api:document-download', args=(document.pk,) 'rest_api:document-download', args=(document.pk,)
) )
) )
buf = BytesIO()
buf.write(response.content)
self.assertEqual( with document.open() as file_object:
HASH_FUNCTION(buf.getvalue()), TEST_SMALL_DOCUMENT_CHECKSUM assert_download_response(
) self, response, content=file_object.read(),
basename=TEST_SMALL_DOCUMENT_FILENAME,
del(buf) mime_type='{}; charset=utf-8'.format(document.file_mimetype)
)
def test_document_version_download(self): def test_document_version_download(self):
with open(TEST_SMALL_DOCUMENT_PATH) as file_object: with open(TEST_SMALL_DOCUMENT_PATH) as file_object:
@@ -278,20 +277,22 @@ class DocumentAPITestCase(APITestCase):
file_object=file_object, file_object=file_object,
) )
latest_version = document.latest_version
response = self.client.get( response = self.client.get(
reverse( reverse(
'rest_api:documentversion-download', 'rest_api:documentversion-download',
args=(document.latest_version.pk,) args=(latest_version.pk,)
) )
) )
buf = BytesIO()
buf.write(response.content)
self.assertEqual( with latest_version.open() as file_object:
HASH_FUNCTION(buf.getvalue()), TEST_SMALL_DOCUMENT_CHECKSUM assert_download_response(
) self, response, content=file_object.read(),
basename='{} - {}'.format(
del(buf) TEST_SMALL_DOCUMENT_FILENAME,
latest_version.timestamp
), mime_type='application/octet-stream; charset=utf-8'
)
# TODO: def test_document_set_document_type(self): # TODO: def test_document_set_document_type(self):
# pass # pass
+12 -9
View File
@@ -3,8 +3,8 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from actstream.models import Action 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 ( from user_management.tests.literals import (
TEST_USER_PASSWORD, TEST_USER_USERNAME TEST_USER_PASSWORD, TEST_USER_USERNAME
) )
@@ -14,7 +14,6 @@ from ..permissions import (
permission_document_download, permission_document_view permission_document_download, permission_document_view
) )
from .test_views import GenericDocumentViewTestCase from .test_views import GenericDocumentViewTestCase
@@ -32,17 +31,14 @@ class DocumentEventsTestCase(GenericDocumentViewTestCase):
Action.objects.all().delete() Action.objects.all().delete()
response = self.post( response = self.get(
'documents:document_download', args=(self.document.pk,) '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)), []) self.assertEqual(list(Action.objects.any(obj=self.document)), [])
@skip_file_descriptor_check
def test_document_download_event_with_permissions(self): def test_document_download_event_with_permissions(self):
# TODO: Skip this test's file descriptor check until it gets migrate
# SingleObjectDownloadView CBV
self.login( self.login(
username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD
) )
@@ -53,12 +49,19 @@ class DocumentEventsTestCase(GenericDocumentViewTestCase):
permission_document_download.stored_permission 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,), '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() event = Action.objects.any(obj=self.document).first()
self.assertEqual(event.verb, event_document_download.name) self.assertEqual(event.verb, event_document_download.name)
+1 -1
View File
@@ -94,7 +94,7 @@ class DocumentsLinksTestCase(GenericDocumentViewTestCase):
self.assertEqual( self.assertEqual(
resolved_link.url, resolved_link.url,
reverse( reverse(
'documents:document_version_download', 'documents:document_version_download_form',
args=(self.document.latest_version.pk,) args=(self.document.latest_version.pk,)
) )
) )
+1 -1
View File
@@ -4,7 +4,7 @@ from datetime import timedelta
import time import time
from common.tests import BaseTestCase from common.tests import BaseTestCase
from django.test import TestCase, override_settings from django.test import override_settings
from ..exceptions import NewDocumentVersionNotAllowed from ..exceptions import NewDocumentVersionNotAllowed
from ..literals import STUB_EXPIRATION_INTERVAL from ..literals import STUB_EXPIRATION_INTERVAL
+64 -67
View File
@@ -4,9 +4,9 @@ from __future__ import unicode_literals
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.test import override_settings 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 common.tests.test_views import GenericViewTestCase
from converter.models import Transformation from converter.models import Transformation
from converter.permissions import permission_transformation_delete 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 ..literals import DEFAULT_DELETE_PERIOD, DEFAULT_DELETE_TIME_UNIT
from ..models import ( from ..models import DeletedDocument, Document, DocumentType
DeletedDocument, Document, DocumentType, HASH_FUNCTION
)
from ..permissions import ( from ..permissions import (
permission_document_create, permission_document_delete, permission_document_create, permission_document_delete,
permission_document_download, permission_document_properties_edit, permission_document_download, permission_document_properties_edit,
@@ -30,7 +28,7 @@ from ..permissions import (
from .literals import ( from .literals import (
TEST_DOCUMENT_TYPE, TEST_DOCUMENT_TYPE_QUICK_LABEL, 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 Document.objects.first().document_type, document_type
) )
@skip_file_descriptor_check def test_document_download_view_no_permission(self):
def test_document_download_user_view(self):
# TODO: Skip this test's file descriptor check until it gets migrate
# SingleObjectDownloadView CBV
self.login( self.login(
username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD
) )
self.assertEqual(Document.objects.count(), 1) response = self.get(
response = self.post(
'documents:document_download', args=(self.document.pk,) '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( self.role.permissions.add(
permission_document_download.stored_permission permission_document_download.stored_permission
) )
# Set the expected_content_type for common.tests.mixins.ContentTypeCheckMixin # Set the expected_content_type for
self.expected_content_type = self.document.file_mimetype # 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,) 'documents:document_download', args=(self.document.pk,)
) )
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
buf = BytesIO() with self.document.open() as file_object:
buf.write(response.content) assert_download_response(
self, response, content=file_object.read(),
self.assertEqual( basename=TEST_SMALL_DOCUMENT_FILENAME,
HASH_FUNCTION(buf.getvalue()), TEST_SMALL_DOCUMENT_CHECKSUM mime_type=self.document.file_mimetype
) )
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
def test_document_multiple_download_view_no_permission(self):
self.login( self.login(
username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD
) )
self.assertEqual(Document.objects.count(), 1) response = self.get(
response = self.post(
'documents:document_multiple_download', 'documents:document_multiple_download',
data={'id_list': self.document.pk} 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( self.role.permissions.add(
permission_document_download.stored_permission permission_document_download.stored_permission
) )
# Set the expected_content_type for common.tests.mixins.ContentTypeCheckMixin # Set the expected_content_type for
self.expected_content_type = self.document.file_mimetype # 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', 'documents:document_multiple_download',
data={'id_list': self.document.pk} data={'id_list': self.document.pk}
) )
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
buf = BytesIO() with self.document.open() as file_object:
buf.write(response.content) assert_download_response(
self, response, content=file_object.read(),
self.assertEqual( basename=TEST_SMALL_DOCUMENT_FILENAME,
HASH_FUNCTION(buf.getvalue()), TEST_SMALL_DOCUMENT_CHECKSUM mime_type=self.document.file_mimetype
) )
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
def test_document_version_download_view_no_permission(self):
self.login( self.login(
username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD
) )
self.assertEqual(Document.objects.count(), 1) response = self.get(
response = self.post(
'documents:document_version_download', args=( 'documents:document_version_download', args=(
self.document.latest_version.pk, 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( self.role.permissions.add(
permission_document_download.stored_permission permission_document_download.stored_permission
) )
# Set the expected_content_type for common.tests.mixins.ContentTypeCheckMixin # Set the expected_content_type for
self.expected_content_type = self.document.file_mimetype # 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=( 'documents:document_version_download', args=(
self.document.latest_version.pk, self.document.latest_version.pk,
) )
@@ -340,14 +338,14 @@ class DocumentsViewsTestCase(GenericDocumentViewTestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
buf = BytesIO() with self.document.open() as file_object:
buf.write(response.content) assert_download_response(
self, response, content=file_object.read(),
self.assertEqual( basename='{} - {}'.format(
HASH_FUNCTION(buf.getvalue()), TEST_SMALL_DOCUMENT_CHECKSUM TEST_SMALL_DOCUMENT_FILENAME,
) self.document.latest_version.timestamp
), mime_type='application/octet-stream; charset=utf-8'
del(buf) )
def test_document_update_page_count_view_no_permission(self): def test_document_update_page_count_view_no_permission(self):
self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD) 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.assertContains(response, text='queued', status_code=200)
self.assertEqual(self.document.pages.count(), page_count) self.assertEqual(self.document.pages.count(), page_count)
def test_document_multiple_update_page_count_view_no_permission(self): def test_document_multiple_update_page_count_view_no_permission(self):
self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD) self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD)
+20 -6
View File
@@ -15,7 +15,8 @@ from .api_views import (
from .settings import setting_print_size, setting_display_size from .settings import setting_print_size, setting_display_size
from .views import ( from .views import (
ClearImageCacheView, DeletedDocumentDeleteView, ClearImageCacheView, DeletedDocumentDeleteView,
DeletedDocumentDeleteManyView, DeletedDocumentListView, DocumentEditView, DeletedDocumentDeleteManyView, DeletedDocumentListView,
DocumentDownloadFormView, DocumentDownloadView, DocumentEditView,
DocumentListView, DocumentPageView, DocumentPageListView, DocumentListView, DocumentPageView, DocumentPageListView,
DocumentPageViewResetView, DocumentPreviewView, DocumentRestoreView, DocumentPageViewResetView, DocumentPreviewView, DocumentRestoreView,
DocumentRestoreManyView, DocumentTrashView, DocumentTrashManyView, DocumentRestoreManyView, DocumentTrashView, DocumentTrashManyView,
@@ -23,6 +24,7 @@ from .views import (
DocumentTypeDocumentListView, DocumentTypeFilenameCreateView, DocumentTypeDocumentListView, DocumentTypeFilenameCreateView,
DocumentTypeFilenameDeleteView, DocumentTypeFilenameEditView, DocumentTypeFilenameDeleteView, DocumentTypeFilenameEditView,
DocumentTypeFilenameListView, DocumentTypeListView, DocumentTypeEditView, DocumentTypeFilenameListView, DocumentTypeListView, DocumentTypeEditView,
DocumentVersionDownloadFormView, DocumentVersionDownloadView,
DocumentVersionListView, DocumentVersionRevertView, DocumentView, DocumentVersionListView, DocumentVersionRevertView, DocumentView,
EmptyTrashCanView, RecentDocumentListView EmptyTrashCanView, RecentDocumentListView
) )
@@ -107,13 +109,20 @@ urlpatterns = patterns(
'size': setting_print_size.value 'size': setting_print_size.value
}, 'document_display_print' }, 'document_display_print'
), ),
url( 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' name='document_download'
), ),
url( 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' name='document_multiple_download'
), ),
url( url(
@@ -127,8 +136,13 @@ urlpatterns = patterns(
name='document_version_list' name='document_version_list'
), ),
url( url(
r'^document/version/(?P<document_version_pk>\d+)/download/$', r'^document/version/(?P<pk>\d+)/download/form/$',
'document_download', name='document_version_download' DocumentVersionDownloadFormView.as_view(),
name='document_version_download_form'
),
url(
r'^document/version/(?P<pk>\d+)/download/$',
DocumentVersionDownloadView.as_view(), name='document_version_download'
), ),
url( url(
r'^document/version/(?P<pk>\d+)/revert/$', r'^document/version/(?P<pk>\d+)/revert/$',
+195 -138
View File
@@ -18,8 +18,9 @@ from django.views.generic import RedirectView
from acls.models import AccessControlList from acls.models import AccessControlList
from common.compressed_files import CompressedFile from common.compressed_files import CompressedFile
from common.generics import ( from common.generics import (
ConfirmView, SimpleView, SingleObjectCreateView, SingleObjectDeleteView, ConfirmView, FormView, SimpleView, SingleObjectCreateView,
SingleObjectDetailView, SingleObjectEditView, SingleObjectListView SingleObjectDeleteView, SingleObjectDetailView, SingleObjectDownloadView,
SingleObjectEditView, SingleObjectListView
) )
from common.mixins import MultipleInstanceActionMixin from common.mixins import MultipleInstanceActionMixin
from converter.literals import ( from converter.literals import (
@@ -27,7 +28,6 @@ from converter.literals import (
) )
from converter.models import Transformation from converter.models import Transformation
from converter.permissions import permission_transformation_delete from converter.permissions import permission_transformation_delete
from filetransfers.api import serve_file
from permissions import Permission from permissions import Permission
from .events import event_document_download, event_document_view from .events import event_document_download, event_document_view
@@ -36,7 +36,9 @@ from .forms import (
DocumentPropertiesForm, DocumentTypeSelectForm, DocumentPropertiesForm, DocumentTypeSelectForm,
DocumentTypeFilenameForm_create, PrintForm 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 ( from .models import (
DeletedDocument, Document, DocumentType, DocumentPage, DeletedDocument, Document, DocumentType, DocumentPage,
DocumentTypeFilename, DocumentVersion, RecentDocument 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') 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): class DocumentDownloadFormView(FormView):
previous = request.POST.get('previous', request.GET.get('previous', request.META.get('HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)))) form_class = DocumentDownloadForm
model = Document
multiple_download_view = 'documents:document_multiple_download'
single_download_view = 'documents:document_download'
if document_id: def get_document_queryset(self):
documents = Document.objects.filter(pk=document_id) id_list = self.request.GET.get(
elif document_id_list: 'id_list', self.request.POST.get('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
) )
try: if not id_list:
Permission.check_permissions( id_list = self.kwargs['pk']
request.user, (permission_document_download,)
)
except PermissionDenied:
documents = AccessControlList.objects.filter_by_access(
permission_document_download, request.user, documents
)
if not documents: return self.model.objects.filter(
messages.error( pk__in=id_list.split(',')
request, _('Must provide at least one document or version.') ).filter(is_stub=False)
)
return HttpResponseRedirect(
request.META.get(
'HTTP_REFERER', reverse(settings.LOGIN_REDIRECT_URL)
)
)
if document_version_pk: def get_extra_context(self):
queryset = DocumentVersion.objects.filter(pk=document_version_pk) subtemplates_list = [
else: {
queryset = DocumentVersion.objects.filter( 'name': 'appearance/generic_list_subtemplate.html',
pk__in=[document.latest_version.pk for document in documents] 'context': {
) 'object_list': self.queryset,
'hide_link': True,
subtemplates_list = [] 'hide_links': True,
subtemplates_list.append( 'hide_multi_item_actions': True,
{ }
'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'},
),
} }
]
context = {
'submit_label': _('Download'),
'subtemplates_list': subtemplates_list,
'title': _('Download documents'),
} }
)
if request.method == 'POST': if self.queryset.count() == 1:
form = DocumentDownloadForm(request.POST, queryset=queryset) context['object'] = self.queryset.first()
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
)
compressed_file.close() return context
return serve_file( def get_form_kwargs(self):
request, kwargs = super(DocumentDownloadFormView, self).get_form_kwargs()
compressed_file.as_file( self.queryset = self.get_queryset()
form.cleaned_data['zip_filename'] kwargs.update({'queryset': self.queryset})
), return kwargs
save_as='"%s"' % form.cleaned_data['zip_filename'],
content_type='application/zip' def form_valid(self, form):
) querystring = urlencode(
except Exception as exception: {
if settings.DEBUG: 'compressed': form.cleaned_data['compressed'],
raise 'zip_filename': form.cleaned_data['zip_filename'],
else: 'id_list': ','.join(
messages.error(request, exception) map(str, self.queryset.values_list('pk', flat=True))
return HttpResponseRedirect( )
request.META['HTTP_REFERER'] }, 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: else:
try: raise PermissionDenied
# 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']
)
else: return DocumentDownloadView.VirtualFile(
form = DocumentDownloadForm(queryset=queryset) DocumentDownloadView.get_item_file(item=item),
name=DocumentDownloadView.get_item_label(
context = { item=item
'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)
)
def document_multiple_download(request): class DocumentVersionDownloadFormView(DocumentDownloadFormView):
return document_download( model = DocumentVersion
request, document_id_list=request.GET.get( multiple_download_view = None
'id_list', request.POST.get('id_list', '') single_download_view = 'documents:document_version_download'
).split(',')
) 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): def document_update_page_count(request, document_id=None, document_id_list=None):
+1 -1
View File
@@ -11,7 +11,7 @@ from .permissions import permission_events_view
def get_kwargs_factory(variable_name): def get_kwargs_factory(variable_name):
def get_kwargs(context): def get_kwargs(context):
ContentType = apps.get_model( ContentType = apps.get_model(
app_label='django', model_name='ContentType' app_label='contenttypes', model_name='ContentType'
) )
content_type = ContentType.objects.get_for_model( content_type = ContentType.objects.get_for_model(
-1
View File
@@ -2,7 +2,6 @@ from __future__ import absolute_import, unicode_literals
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from acls.models import AccessControlList
from documents.tests.test_views import GenericDocumentViewTestCase from documents.tests.test_views import GenericDocumentViewTestCase
from user_management.tests import ( from user_management.tests import (
TEST_USER_USERNAME, TEST_USER_PASSWORD TEST_USER_USERNAME, TEST_USER_PASSWORD
+31 -6
View File
@@ -13,12 +13,37 @@ class Migration(migrations.Migration):
migrations.CreateModel( migrations.CreateModel(
name='MessageOfTheDay', name='MessageOfTheDay',
fields=[ fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), (
('label', models.CharField(max_length=32, verbose_name='Label')), 'id', models.AutoField(
('message', models.TextField(verbose_name='Message', blank=True)), verbose_name='ID', serialize=False, auto_created=True,
('enabled', models.BooleanField(default=True, verbose_name='Enabled')), primary_key=True
('start_datetime', models.DateTimeField(verbose_name='Start date time', blank=True)), )
('end_datetime', models.DateTimeField(verbose_name='End date time', blank=True)), ),
(
'label', models.CharField(
max_length=32, verbose_name='Label'
)
),
(
'message', models.TextField(
verbose_name='Message', blank=True
)
),
(
'enabled', models.BooleanField(
default=True, verbose_name='Enabled'
)
),
(
'start_datetime', models.DateTimeField(
verbose_name='Start date time', blank=True
)
),
(
'end_datetime', models.DateTimeField(
verbose_name='End date time', blank=True
)
),
], ],
options={ options={
'verbose_name': 'Message of the day', 'verbose_name': 'Message of the day',
@@ -14,11 +14,15 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='messageoftheday', model_name='messageoftheday',
name='end_datetime', name='end_datetime',
field=models.DateTimeField(null=True, verbose_name='End date time', blank=True), field=models.DateTimeField(
null=True, verbose_name='End date time', blank=True
),
), ),
migrations.AlterField( migrations.AlterField(
model_name='messageoftheday', model_name='messageoftheday',
name='start_datetime', name='start_datetime',
field=models.DateTimeField(null=True, verbose_name='Start date time', blank=True), field=models.DateTimeField(
null=True, verbose_name='Start date time', blank=True
),
), ),
] ]
@@ -14,21 +14,35 @@ class Migration(migrations.Migration):
migrations.AlterField( migrations.AlterField(
model_name='message', model_name='message',
name='end_datetime', name='end_datetime',
field=models.DateTimeField(help_text='Date and time until when this message is to be displayed.', null=True, verbose_name='End date time', blank=True), field=models.DateTimeField(
help_text='Date and time until when this message is to be '
'displayed.', null=True, verbose_name='End date time',
blank=True
),
), ),
migrations.AlterField( migrations.AlterField(
model_name='message', model_name='message',
name='label', name='label',
field=models.CharField(help_text='Short description of this message.', max_length=32, verbose_name='Label'), field=models.CharField(
help_text='Short description of this message.', max_length=32,
verbose_name='Label'
),
), ),
migrations.AlterField( migrations.AlterField(
model_name='message', model_name='message',
name='message', name='message',
field=models.TextField(help_text='The actual message to be displayed.', verbose_name='Message'), field=models.TextField(
help_text='The actual message to be displayed.',
verbose_name='Message'
),
), ),
migrations.AlterField( migrations.AlterField(
model_name='message', model_name='message',
name='start_datetime', name='start_datetime',
field=models.DateTimeField(help_text='Date and time after which this message will be displayed.', null=True, verbose_name='Start date time', blank=True), field=models.DateTimeField(
help_text='Date and time after which this message will be '
'displayed.', null=True, verbose_name='Start date time',
blank=True
),
), ),
] ]
+3 -1
View File
@@ -10,7 +10,9 @@ urlpatterns = patterns(
'', '',
url(r'^list/$', MessageListView.as_view(), name='message_list'), url(r'^list/$', MessageListView.as_view(), name='message_list'),
url(r'^create/$', MessageCreateView.as_view(), name='message_create'), url(r'^create/$', MessageCreateView.as_view(), name='message_create'),
url(r'^(?P<pk>\d+)/edit/$', MessageEditView.as_view(), name='message_edit'), url(
r'^(?P<pk>\d+)/edit/$', MessageEditView.as_view(), name='message_edit'
),
url( url(
r'^(?P<pk>\d+)/delete/$', MessageDeleteView.as_view(), r'^(?P<pk>\d+)/delete/$', MessageDeleteView.as_view(),
name='message_delete' name='message_delete'
-4
View File
@@ -3,7 +3,6 @@ from __future__ import unicode_literals
import logging import logging
from kombu import Exchange, Queue from kombu import Exchange, Queue
import sh
from django.apps import apps from django.apps import apps
from django.db.models.signals import post_save from django.db.models.signals import post_save
@@ -29,9 +28,6 @@ from .links import (
link_document_type_submit, link_entry_list link_document_type_submit, link_entry_list
) )
from .permissions import permission_ocr_document, permission_ocr_content_view from .permissions import permission_ocr_document, permission_ocr_content_view
from .settings import (
setting_pdftotext_path, setting_tesseract_path
)
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
-1
View File
@@ -11,7 +11,6 @@ import subprocess
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from common.settings import setting_temporary_directory
from common.utils import copyfile, fs_cleanup, mkstemp from common.utils import copyfile, fs_cleanup, mkstemp
from .exceptions import ParserError, NoMIMETypeMatch from .exceptions import ParserError, NoMIMETypeMatch
-3
View File
@@ -1,11 +1,8 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import psutil
from django.core.files.base import File from django.core.files.base import File
from django.test import override_settings from django.test import override_settings
from common.settings import setting_temporary_directory
from common.tests import BaseTestCase from common.tests import BaseTestCase
from documents.models import DocumentType from documents.models import DocumentType
from documents.tests import ( from documents.tests import (
@@ -35,7 +35,6 @@ class StatisticsViewTestCase(GenericViewTestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_statistic_namespace_list_view_no_permissions(self): def test_statistic_namespace_list_view_no_permissions(self):
self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD) self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD)
@@ -4,7 +4,7 @@ import os
import zipfile import zipfile
try: try:
import zlib import zlib # NOQA
COMPRESSION = zipfile.ZIP_DEFLATED COMPRESSION = zipfile.ZIP_DEFLATED
except: except:
COMPRESSION = zipfile.ZIP_STORED COMPRESSION = zipfile.ZIP_STORED
-1
View File
@@ -55,7 +55,6 @@ INSTALLED_APPS = (
'compressor', 'compressor',
'corsheaders', 'corsheaders',
'djcelery', 'djcelery',
'filetransfers',
'formtools', 'formtools',
'mptt', 'mptt',
'pure_pagination', 'pure_pagination',
-1
View File
@@ -11,7 +11,6 @@ django-colorful==1.2
django-compressor==2.1 django-compressor==2.1
django-cors-headers==1.2.2 django-cors-headers==1.2.2
django-downloadview==1.9 django-downloadview==1.9
django-filetransfers==0.1.0
django-formtools==1.0 django-formtools==1.0
django-pure-pagination==0.3.0 django-pure-pagination==0.3.0
django-model-utils==2.6 django-model-utils==2.6