Complete conversion of download views to CBV views using django-downloadview.
This also removes dependency on the filetransfers library.
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
- Remove the installation app
|
||||
- Add support for document page search
|
||||
- Remove recent searches feature
|
||||
- Remove dependency on the django-filetransfer library
|
||||
|
||||
2.1.4 (2016-10-28)
|
||||
==================
|
||||
|
||||
@@ -13,6 +13,7 @@ Other changes
|
||||
- Remove the installation app
|
||||
- Add support for page search
|
||||
- Remove recent searches feature
|
||||
- Remove dependency on the django-filetransfer library
|
||||
|
||||
Removals
|
||||
--------
|
||||
@@ -43,6 +44,7 @@ existing installation.
|
||||
|
||||
Next upgrade/add the new requirements::
|
||||
|
||||
$ pip uninstall -y django-filetransfers
|
||||
$ pip install --upgrade -r requirements.txt
|
||||
|
||||
Common steps
|
||||
|
||||
@@ -10,7 +10,9 @@ from .permissions import permission_acl_view, permission_acl_edit
|
||||
|
||||
def get_kwargs_factory(variable_name):
|
||||
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(
|
||||
context[variable_name]
|
||||
|
||||
@@ -23,7 +23,9 @@
|
||||
|
||||
<form action="{% url 'common:multi_object_action_view' %}" class="pure-form" method="get">
|
||||
{% 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 %}
|
||||
<fieldset>
|
||||
{{ multi_item_form }}
|
||||
|
||||
@@ -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.
|
||||
''')
|
||||
|
||||
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='''
|
||||
Copyright (c) James Pacileo and contributors.
|
||||
All rights reserved.
|
||||
|
||||
@@ -3,7 +3,7 @@ from __future__ import unicode_literals
|
||||
import zipfile
|
||||
|
||||
try:
|
||||
import zlib
|
||||
import zlib # NOQA
|
||||
COMPRESSION = zipfile.ZIP_DEFLATED
|
||||
except:
|
||||
COMPRESSION = zipfile.ZIP_STORED
|
||||
|
||||
@@ -14,8 +14,7 @@ from django.views.generic.edit import (
|
||||
)
|
||||
from django.views.generic.list import ListView
|
||||
|
||||
from django_downloadview import VirtualDownloadView
|
||||
from django_downloadview import VirtualFile
|
||||
from django_downloadview import VirtualDownloadView, VirtualFile
|
||||
from pure_pagination.mixins import PaginationMixin
|
||||
|
||||
from .forms import ChoiceForm
|
||||
|
||||
@@ -12,9 +12,16 @@ class Command(management.BaseCommand):
|
||||
def handle(self, *args, **options):
|
||||
management.call_command('createsettings', interactive=False)
|
||||
try:
|
||||
result = management.call_command('migrate', interactive=False)
|
||||
except OperationalError as exception:
|
||||
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.'))
|
||||
management.call_command('migrate', interactive=False)
|
||||
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.'
|
||||
)
|
||||
)
|
||||
raise
|
||||
management.call_command('createautoadmin', interactive=False)
|
||||
post_initial_setup.send(sender=self)
|
||||
|
||||
@@ -159,12 +159,6 @@ class RedirectionMixin(object):
|
||||
post_action_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):
|
||||
post_action_redirect = self.get_post_action_redirect()
|
||||
action_cancel_redirect = self.get_action_cancel_redirect()
|
||||
@@ -188,6 +182,9 @@ class RedirectionMixin(object):
|
||||
RedirectionMixin, self
|
||||
).dispatch(request, *args, **kwargs)
|
||||
|
||||
def get_action_cancel_redirect(self):
|
||||
return self.action_cancel_redirect
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super(RedirectionMixin, self).get_context_data(**kwargs)
|
||||
context.update(
|
||||
@@ -199,6 +196,9 @@ class RedirectionMixin(object):
|
||||
|
||||
return context
|
||||
|
||||
def get_post_action_redirect(self):
|
||||
return self.post_action_redirect
|
||||
|
||||
def get_success_url(self):
|
||||
return self.next_url or self.previous_url
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
def skip_file_descriptor_check(func):
|
||||
def func_wrapper(item):
|
||||
item._skip_file_descriptor_test = True
|
||||
return func(item)
|
||||
return func_wrapper
|
||||
def func_wrapper(item):
|
||||
item._skip_file_descriptor_test = True
|
||||
return func(item)
|
||||
return func_wrapper
|
||||
|
||||
@@ -66,7 +66,7 @@ class TempfileCheckMixin(object):
|
||||
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 '
|
||||
'same. Orphan entries: {}'.format(
|
||||
','.join(final_temporary_items-self._temporary_items)
|
||||
','.join(final_temporary_items - self._temporary_items)
|
||||
)
|
||||
)
|
||||
super(TempfileCheckMixin, self).tearDown()
|
||||
|
||||
@@ -6,7 +6,6 @@ from django.contrib.auth.models import Group
|
||||
from django.core.urlresolvers import clear_url_caches, reverse
|
||||
from django.http import HttpResponse
|
||||
from django.template import Context, Template
|
||||
from django.test import TestCase
|
||||
|
||||
from permissions import Permission
|
||||
from permissions.models import Role
|
||||
|
||||
@@ -13,7 +13,9 @@ from .permissions import (
|
||||
|
||||
def get_kwargs_factory(variable_name):
|
||||
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(
|
||||
context[variable_name]
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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())
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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/$',
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -11,7 +11,7 @@ from .permissions import permission_events_view
|
||||
def get_kwargs_factory(variable_name):
|
||||
def get_kwargs(context):
|
||||
ContentType = apps.get_model(
|
||||
app_label='django', model_name='ContentType'
|
||||
app_label='contenttypes', model_name='ContentType'
|
||||
)
|
||||
|
||||
content_type = ContentType.objects.get_for_model(
|
||||
|
||||
@@ -2,7 +2,6 @@ from __future__ import absolute_import, unicode_literals
|
||||
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
from acls.models import AccessControlList
|
||||
from documents.tests.test_views import GenericDocumentViewTestCase
|
||||
from user_management.tests import (
|
||||
TEST_USER_USERNAME, TEST_USER_PASSWORD
|
||||
|
||||
@@ -13,12 +13,37 @@ class Migration(migrations.Migration):
|
||||
migrations.CreateModel(
|
||||
name='MessageOfTheDay',
|
||||
fields=[
|
||||
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=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)),
|
||||
(
|
||||
'id', models.AutoField(
|
||||
verbose_name='ID', serialize=False, auto_created=True,
|
||||
primary_key=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={
|
||||
'verbose_name': 'Message of the day',
|
||||
|
||||
@@ -14,11 +14,15 @@ class Migration(migrations.Migration):
|
||||
migrations.AlterField(
|
||||
model_name='messageoftheday',
|
||||
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(
|
||||
model_name='messageoftheday',
|
||||
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(
|
||||
model_name='message',
|
||||
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(
|
||||
model_name='message',
|
||||
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(
|
||||
model_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(
|
||||
model_name='message',
|
||||
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
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
@@ -10,7 +10,9 @@ urlpatterns = patterns(
|
||||
'',
|
||||
url(r'^list/$', MessageListView.as_view(), name='message_list'),
|
||||
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(
|
||||
r'^(?P<pk>\d+)/delete/$', MessageDeleteView.as_view(),
|
||||
name='message_delete'
|
||||
|
||||
@@ -3,7 +3,6 @@ from __future__ import unicode_literals
|
||||
import logging
|
||||
|
||||
from kombu import Exchange, Queue
|
||||
import sh
|
||||
|
||||
from django.apps import apps
|
||||
from django.db.models.signals import post_save
|
||||
@@ -29,9 +28,6 @@ from .links import (
|
||||
link_document_type_submit, link_entry_list
|
||||
)
|
||||
from .permissions import permission_ocr_document, permission_ocr_content_view
|
||||
from .settings import (
|
||||
setting_pdftotext_path, setting_tesseract_path
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@ import subprocess
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from common.settings import setting_temporary_directory
|
||||
from common.utils import copyfile, fs_cleanup, mkstemp
|
||||
|
||||
from .exceptions import ParserError, NoMIMETypeMatch
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import psutil
|
||||
|
||||
from django.core.files.base import File
|
||||
from django.test import override_settings
|
||||
|
||||
from common.settings import setting_temporary_directory
|
||||
from common.tests import BaseTestCase
|
||||
from documents.models import DocumentType
|
||||
from documents.tests import (
|
||||
|
||||
@@ -35,7 +35,6 @@ class StatisticsViewTestCase(GenericViewTestCase):
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
|
||||
def test_statistic_namespace_list_view_no_permissions(self):
|
||||
self.login(username=TEST_USER_USERNAME, password=TEST_USER_PASSWORD)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import os
|
||||
import zipfile
|
||||
|
||||
try:
|
||||
import zlib
|
||||
import zlib # NOQA
|
||||
COMPRESSION = zipfile.ZIP_DEFLATED
|
||||
except:
|
||||
COMPRESSION = zipfile.ZIP_STORED
|
||||
|
||||
@@ -55,7 +55,6 @@ INSTALLED_APPS = (
|
||||
'compressor',
|
||||
'corsheaders',
|
||||
'djcelery',
|
||||
'filetransfers',
|
||||
'formtools',
|
||||
'mptt',
|
||||
'pure_pagination',
|
||||
|
||||
@@ -11,7 +11,6 @@ django-colorful==1.2
|
||||
django-compressor==2.1
|
||||
django-cors-headers==1.2.2
|
||||
django-downloadview==1.9
|
||||
django-filetransfers==0.1.0
|
||||
django-formtools==1.0
|
||||
django-pure-pagination==0.3.0
|
||||
django-model-utils==2.6
|
||||
|
||||
Reference in New Issue
Block a user