Refactor rest_api app and the method end points are registered. All apps API URL endpoints are now registered under the 'rest_api' namespace.
Update DRF and DRF swagger versions. Update all apps API registration method.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -80,7 +80,7 @@ class DocumentsApp(MayanAppConfig):
|
||||
def ready(self):
|
||||
super(DocumentsApp, self).ready()
|
||||
|
||||
APIEndPoint('documents')
|
||||
APIEndPoint(app=self, version_string='1')
|
||||
|
||||
MissingItem(
|
||||
label=_('Create a document type'),
|
||||
|
||||
@@ -20,7 +20,9 @@ from converter import (
|
||||
converter_class, TransformationResize, TransformationRotate,
|
||||
TransformationZoom
|
||||
)
|
||||
from converter.exceptions import InvalidOfficeFormat, UnknownFileFormat
|
||||
from converter.exceptions import (
|
||||
InvalidOfficeFormat, PageCountError, UnknownFileFormat
|
||||
)
|
||||
from converter.literals import DEFAULT_ZOOM_LEVEL, DEFAULT_ROTATION
|
||||
from converter.models import Transformation
|
||||
from mimetype.api import get_mimetype
|
||||
@@ -150,6 +152,7 @@ class Document(models.Model):
|
||||
in_trash = models.BooleanField(
|
||||
default=False, editable=False, verbose_name=_('In trash?')
|
||||
)
|
||||
#TODO: set editable to False
|
||||
deleted_date_time = models.DateTimeField(
|
||||
blank=True, editable=True, null=True,
|
||||
verbose_name=_('Date and time trashed')
|
||||
@@ -431,25 +434,24 @@ class DocumentVersion(models.Model):
|
||||
file_object=file_object, mime_type=self.mimetype
|
||||
)
|
||||
detected_pages = converter.get_page_count()
|
||||
except UnknownFileFormat:
|
||||
except PageCountError:
|
||||
# If converter backend doesn't understand the format,
|
||||
# use 1 as the total page count
|
||||
detected_pages = 1
|
||||
# TODO: should be no pages instead?
|
||||
pass
|
||||
else:
|
||||
with transaction.atomic():
|
||||
self.pages.all().delete()
|
||||
|
||||
with transaction.atomic():
|
||||
self.pages.all().delete()
|
||||
for page_number in range(detected_pages):
|
||||
DocumentPage.objects.create(
|
||||
document_version=self, page_number=page_number + 1
|
||||
)
|
||||
|
||||
for page_number in range(detected_pages):
|
||||
DocumentPage.objects.create(
|
||||
document_version=self, page_number=page_number + 1
|
||||
)
|
||||
# TODO: is this needed anymore
|
||||
if save:
|
||||
self.save()
|
||||
|
||||
# TODO: is this needed anymore
|
||||
if save:
|
||||
self.save()
|
||||
|
||||
return detected_pages
|
||||
return detected_pages
|
||||
|
||||
def revert(self, user=None):
|
||||
"""
|
||||
@@ -670,8 +672,8 @@ class DocumentPage(models.Model):
|
||||
as_base64 = kwargs.pop('as_base64', False)
|
||||
transformations = kwargs.pop('transformations', [])
|
||||
size = kwargs.pop('size', setting_display_size.value)
|
||||
rotation = kwargs.pop('rotation', DEFAULT_ROTATION)
|
||||
zoom_level = kwargs.pop('zoom', DEFAULT_ZOOM_LEVEL)
|
||||
rotation = int(kwargs.pop('rotation', DEFAULT_ROTATION) or DEFAULT_ROTATION)
|
||||
zoom_level = int(kwargs.pop('zoom', DEFAULT_ZOOM_LEVEL) or DEFAULT_ZOOM_LEVEL)
|
||||
|
||||
if zoom_level < setting_zoom_min_level.value:
|
||||
zoom_level = setting_zoom_min_level.value
|
||||
|
||||
@@ -2,66 +2,181 @@ from __future__ import unicode_literals
|
||||
|
||||
from rest_framework import serializers
|
||||
|
||||
from .models import (Document, DocumentVersion, DocumentPage, DocumentType,
|
||||
RecentDocument)
|
||||
from .settings import setting_language, setting_language_choices
|
||||
from common.models import SharedUploadedFile
|
||||
|
||||
from .literals import DOCUMENT_IMAGE_TASK_TIMEOUT
|
||||
from .models import (
|
||||
Document, DocumentVersion, DocumentPage, DocumentType, RecentDocument
|
||||
)
|
||||
from .settings import setting_language
|
||||
from .tasks import task_get_document_page_image, task_upload_new_version
|
||||
|
||||
|
||||
class DocumentPageImageSerializer(serializers.Serializer):
|
||||
data = serializers.SerializerMethodField()
|
||||
|
||||
def get_data(self, instance):
|
||||
request = self.context['request']
|
||||
size = request.GET.get('size')
|
||||
zoom = request.GET.get('zoom')
|
||||
rotation = request.GET.get('rotation')
|
||||
|
||||
task = task_get_document_page_image.apply_async(
|
||||
kwargs=dict(
|
||||
document_page_id=instance.pk, size=size, zoom=zoom,
|
||||
rotation=rotation, as_base64=True
|
||||
)
|
||||
)
|
||||
# TODO: prepend 'data:%s;base64,%s' based on format specified in
|
||||
# async call
|
||||
return task.get(timeout=DOCUMENT_IMAGE_TASK_TIMEOUT)
|
||||
|
||||
|
||||
class DocumentPageSerializer(serializers.HyperlinkedModelSerializer):
|
||||
image = serializers.HyperlinkedIdentityField(
|
||||
view_name='rest_api:documentpage-image'
|
||||
)
|
||||
|
||||
class Meta:
|
||||
extra_kwargs = {
|
||||
'url': {'view_name': 'rest_api:documentpage-detail'},
|
||||
'document_version': {'view_name': 'rest_api:documentversion-detail'}
|
||||
}
|
||||
model = DocumentPage
|
||||
|
||||
|
||||
class DocumentVersionSerializer(serializers.HyperlinkedModelSerializer):
|
||||
pages = DocumentPageSerializer(many=True, required=False, read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = DocumentVersion
|
||||
read_only_fields = ('document',)
|
||||
|
||||
|
||||
class DocumentImageSerializer(serializers.Serializer):
|
||||
status = serializers.CharField()
|
||||
data = serializers.CharField()
|
||||
|
||||
|
||||
class DocumentTypeSerializer(serializers.ModelSerializer):
|
||||
documents = serializers.SerializerMethodField('get_documents_count')
|
||||
|
||||
class Meta:
|
||||
model = DocumentType
|
||||
fields = ('id', 'name', 'documents')
|
||||
class DocumentTypeSerializer(serializers.HyperlinkedModelSerializer):
|
||||
documents = serializers.HyperlinkedIdentityField(
|
||||
view_name='rest_api:documenttype-document-list',
|
||||
)
|
||||
documents_count = serializers.SerializerMethodField()
|
||||
|
||||
def get_documents_count(self, obj):
|
||||
return obj.documents.count()
|
||||
|
||||
class Meta:
|
||||
extra_kwargs = {
|
||||
'url': {'view_name': 'rest_api:documenttype-detail'},
|
||||
}
|
||||
fields = (
|
||||
'delete_time_period', 'delete_time_unit', 'documents',
|
||||
'documents_count', 'id', 'label', 'trash_time_period',
|
||||
'trash_time_unit', 'url'
|
||||
)
|
||||
model = DocumentType
|
||||
|
||||
class DocumentSerializer(serializers.ModelSerializer):
|
||||
versions = DocumentVersionSerializer(many=True, read_only=True)
|
||||
# TODO: Deprecate, move this as an entry point of DocumentVersion's pages
|
||||
image = serializers.HyperlinkedIdentityField(view_name='document-image')
|
||||
new_version = serializers.HyperlinkedIdentityField(
|
||||
view_name='document-new-version'
|
||||
)
|
||||
document_type = DocumentTypeSerializer()
|
||||
|
||||
class DocumentVersionSerializer(serializers.HyperlinkedModelSerializer):
|
||||
pages = DocumentPageSerializer(many=True, required=False, read_only=True)
|
||||
revert = serializers.HyperlinkedIdentityField(view_name='rest_api:documentversion-revert')
|
||||
|
||||
class Meta:
|
||||
extra_kwargs = {
|
||||
'document': {'view_name': 'rest_api:document-detail'},
|
||||
'file': {'use_url': False},
|
||||
'url': {'view_name': 'rest_api:documentversion-detail'},
|
||||
}
|
||||
model = DocumentVersion
|
||||
read_only_fields = ('document', 'file')
|
||||
|
||||
|
||||
class DocumentVersionRevertSerializer(DocumentVersionSerializer):
|
||||
class Meta(DocumentVersionSerializer.Meta):
|
||||
read_only_fields = ('comment', 'document',)
|
||||
|
||||
|
||||
class NewDocumentVersionSerializer(serializers.Serializer):
|
||||
comment = serializers.CharField(allow_blank=True)
|
||||
file = serializers.FileField(use_url=False)
|
||||
|
||||
def save(self, document, _user):
|
||||
shared_uploaded_file = SharedUploadedFile.objects.create(
|
||||
file=self.validated_data['file']
|
||||
)
|
||||
|
||||
task_upload_new_version.delay(
|
||||
comment=self.validated_data.get('comment', ''),
|
||||
document_id=document.pk,
|
||||
shared_uploaded_file_id=shared_uploaded_file.pk, user_id=_user.pk
|
||||
)
|
||||
|
||||
|
||||
class DeletedDocumentSerializer(serializers.HyperlinkedModelSerializer):
|
||||
document_type_label = serializers.SerializerMethodField()
|
||||
restore = serializers.HyperlinkedIdentityField(view_name='rest_api:deleteddocument-restore')
|
||||
|
||||
def get_document_type_label(self, instance):
|
||||
return instance.document_type.label
|
||||
|
||||
class Meta:
|
||||
extra_kwargs = {
|
||||
'document_type': {'view_name': 'rest_api:documenttype-detail'},
|
||||
'url': {'view_name': 'rest_api:deleteddocument-detail'}
|
||||
}
|
||||
fields = (
|
||||
'id', 'label', 'image', 'new_version', 'uuid', 'document_type',
|
||||
'description', 'date_added', 'versions'
|
||||
'date_added', 'deleted_date_time', 'description', 'document_type',
|
||||
'document_type_label', 'id', 'label', 'language', 'restore',
|
||||
'url', 'uuid',
|
||||
)
|
||||
model = Document
|
||||
read_only_fields = (
|
||||
'deleted_date_time', 'description', 'document_type', 'label',
|
||||
'language'
|
||||
)
|
||||
|
||||
|
||||
class DocumentSerializer(serializers.HyperlinkedModelSerializer):
|
||||
document_type_label = serializers.SerializerMethodField()
|
||||
latest_version = DocumentVersionSerializer(many=False, read_only=True)
|
||||
versions = serializers.HyperlinkedIdentityField(
|
||||
view_name='rest_api:document-version-list',
|
||||
)
|
||||
|
||||
def get_document_type_label(self, instance):
|
||||
return instance.document_type.label
|
||||
|
||||
class Meta:
|
||||
extra_kwargs = {
|
||||
'document_type': {'view_name': 'rest_api:documenttype-detail'},
|
||||
'url': {'view_name': 'rest_api:document-detail'}
|
||||
}
|
||||
fields = (
|
||||
'date_added', 'description', 'document_type', 'document_type_label',
|
||||
'id', 'label', 'language', 'latest_version', 'url', 'uuid',
|
||||
'versions',
|
||||
)
|
||||
model = Document
|
||||
|
||||
|
||||
class NewDocumentSerializer(serializers.Serializer):
|
||||
description = serializers.CharField(required=False)
|
||||
document_type = serializers.IntegerField()
|
||||
file = serializers.FileField()
|
||||
label = serializers.CharField(required=False)
|
||||
language = serializers.ChoiceField(
|
||||
blank_display_value=None, choices=setting_language_choices.value,
|
||||
default=setting_language.value, required=False
|
||||
)
|
||||
class NewDocumentSerializer(serializers.ModelSerializer):
|
||||
file = serializers.FileField(write_only=True)
|
||||
|
||||
def save(self, _user):
|
||||
document = Document.objects.create(
|
||||
description=self.validated_data.get('description', ''),
|
||||
document_type=self.validated_data['document_type'],
|
||||
label=self.validated_data.get('label', unicode(self.validated_data['file'])),
|
||||
language=self.validated_data.get('language', setting_language.value)
|
||||
)
|
||||
document.save(_user=_user)
|
||||
|
||||
shared_uploaded_file = SharedUploadedFile.objects.create(
|
||||
file=self.validated_data['file']
|
||||
)
|
||||
|
||||
task_upload_new_version.delay(
|
||||
document_id=document.pk,
|
||||
shared_uploaded_file_id=shared_uploaded_file.pk, user_id=_user.pk
|
||||
)
|
||||
|
||||
self.instance = document
|
||||
return document
|
||||
|
||||
class Meta:
|
||||
fields = (
|
||||
'description', 'document_type', 'id', 'file', 'label', 'language',
|
||||
)
|
||||
model = Document
|
||||
|
||||
|
||||
class RecentDocumentSerializer(serializers.ModelSerializer):
|
||||
|
||||
@@ -181,7 +181,7 @@ def task_upload_new_version(self, document_id, shared_uploaded_file_id, user_id,
|
||||
|
||||
with shared_file.open() as file_object:
|
||||
document_version = DocumentVersion(
|
||||
document=document, comment=comment, file=file_object
|
||||
document=document, comment=comment or '', file=file_object
|
||||
)
|
||||
try:
|
||||
document_version.save(_user=user)
|
||||
|
||||
@@ -5,25 +5,23 @@ from __future__ import unicode_literals
|
||||
from json import loads
|
||||
|
||||
from django.contrib.auth.models import User
|
||||
from django.core.files import File
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.test import TestCase
|
||||
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APIClient
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from .models import Document, DocumentType
|
||||
from .test_models import (
|
||||
TEST_ADMIN_PASSWORD, TEST_ADMIN_USERNAME, TEST_ADMIN_EMAIL,
|
||||
TEST_SMALL_DOCUMENT_FILENAME, TEST_DOCUMENT_PATH,
|
||||
TEST_SMALL_DOCUMENT_PATH,
|
||||
TEST_DOCUMENT_TYPE
|
||||
TEST_ADMIN_EMAIL, TEST_ADMIN_PASSWORD, TEST_ADMIN_USERNAME,
|
||||
TEST_DOCUMENT_FILENAME, TEST_DOCUMENT_PATH, TEST_DOCUMENT_TYPE,
|
||||
TEST_SMALL_DOCUMENT_FILENAME, TEST_SMALL_DOCUMENT_PATH,
|
||||
)
|
||||
|
||||
|
||||
class DocumentAPICreateDocumentTestCase(TestCase):
|
||||
class DocumentTypeAPITestCase(APITestCase):
|
||||
"""
|
||||
Functional test to make sure all the moving parts to create a document
|
||||
from the API are working correctly
|
||||
Test the document type API endpoints
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
@@ -31,6 +29,65 @@ class DocumentAPICreateDocumentTestCase(TestCase):
|
||||
username=TEST_ADMIN_USERNAME, email=TEST_ADMIN_EMAIL,
|
||||
password=TEST_ADMIN_PASSWORD
|
||||
)
|
||||
|
||||
self.client.force_authenticate(user=self.admin_user)
|
||||
|
||||
def testDown(self):
|
||||
self.admin_user.delete()
|
||||
|
||||
def test_document_type_create(self):
|
||||
self.assertEqual(DocumentType.objects.all().count(), 0)
|
||||
|
||||
self.client.post(reverse('rest_api:documenttype-list'), {'label': TEST_DOCUMENT_TYPE})
|
||||
|
||||
self.assertEqual(DocumentType.objects.all().count(), 1)
|
||||
self.assertEqual(DocumentType.objects.all().first().label, TEST_DOCUMENT_TYPE)
|
||||
|
||||
def test_document_type_edit_via_put(self):
|
||||
document_type = DocumentType.objects.create(label=TEST_DOCUMENT_TYPE)
|
||||
|
||||
self.client.put(
|
||||
reverse('rest_api:documenttype-detail', args=[document_type.pk]),
|
||||
{'label': TEST_DOCUMENT_TYPE + 'edited'}
|
||||
)
|
||||
|
||||
document_type = DocumentType.objects.get(pk=document_type.pk)
|
||||
self.assertEqual(document_type.label, TEST_DOCUMENT_TYPE + 'edited')
|
||||
|
||||
def test_document_type_edit_via_patch(self):
|
||||
document_type = DocumentType.objects.create(label=TEST_DOCUMENT_TYPE)
|
||||
|
||||
self.client.patch(
|
||||
reverse('rest_api:documenttype-detail', args=[document_type.pk]),
|
||||
{'label': TEST_DOCUMENT_TYPE + 'edited'}
|
||||
)
|
||||
|
||||
document_type = DocumentType.objects.get(pk=document_type.pk)
|
||||
self.assertEqual(document_type.label, TEST_DOCUMENT_TYPE + 'edited')
|
||||
|
||||
def test_document_type_delete(self):
|
||||
document_type = DocumentType.objects.create(label=TEST_DOCUMENT_TYPE)
|
||||
|
||||
self.client.delete(
|
||||
reverse('rest_api:documenttype-detail', args=(document_type.pk,))
|
||||
)
|
||||
|
||||
self.assertEqual(DocumentType.objects.all().count(), 0)
|
||||
|
||||
|
||||
class DocumentAPITestCase(APITestCase):
|
||||
"""
|
||||
Test document API endpoints
|
||||
"""
|
||||
|
||||
def setUp(self):
|
||||
self.admin_user = User.objects.create_superuser(
|
||||
username=TEST_ADMIN_USERNAME, email=TEST_ADMIN_EMAIL,
|
||||
password=TEST_ADMIN_PASSWORD
|
||||
)
|
||||
|
||||
self.client.force_authenticate(user=self.admin_user)
|
||||
|
||||
self.document_type = DocumentType.objects.create(
|
||||
label=TEST_DOCUMENT_TYPE
|
||||
)
|
||||
@@ -40,90 +97,133 @@ class DocumentAPICreateDocumentTestCase(TestCase):
|
||||
ocr_settings.save()
|
||||
|
||||
def tearDown(self):
|
||||
self.document_type.delete()
|
||||
self.admin_user.delete()
|
||||
self.document_type.delete()
|
||||
|
||||
def test_uploading_a_document_using_token_auth(self):
|
||||
# Get the an user token
|
||||
token_client = APIClient()
|
||||
response = token_client.post(
|
||||
reverse('auth_token_obtain'), {
|
||||
'username': TEST_ADMIN_USERNAME,
|
||||
'password': TEST_ADMIN_PASSWORD
|
||||
}
|
||||
)
|
||||
|
||||
# Be able to get authentication token
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
|
||||
# Make sure a token was returned
|
||||
self.assertTrue('token' in response.content)
|
||||
|
||||
token = loads(response.content)['token']
|
||||
|
||||
# Create a new client to simulate a different request
|
||||
document_client = APIClient()
|
||||
|
||||
# Create a blank document with no token in the header
|
||||
# TODO: Fix, must not be able to create the document with API token
|
||||
# with open(TEST_SMALL_DOCUMENT_PATH) as file_descriptor:
|
||||
# response = document_client.post(reverse('document-list'), {'document_type': self.document_type.pk, 'file': file_descriptor})
|
||||
|
||||
# Make sure toke authentication is working, should fail
|
||||
# TODO: FIX failing test: self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
|
||||
document_client.credentials(HTTP_AUTHORIZATION='Token ' + token)
|
||||
|
||||
# Create a blank document
|
||||
with open(TEST_SMALL_DOCUMENT_PATH) as file_descriptor:
|
||||
document_response = document_client.post(
|
||||
reverse('document-list'), {
|
||||
def test_document_upload(self):
|
||||
with open(TEST_DOCUMENT_PATH) as file_descriptor:
|
||||
document_response = self.client.post(
|
||||
reverse('rest_api:document-list'), {
|
||||
'document_type': self.document_type.pk,
|
||||
'file': file_descriptor
|
||||
}
|
||||
)
|
||||
|
||||
document_data = loads(document_response.content)
|
||||
|
||||
self.assertEqual(document_response.status_code, status.HTTP_201_CREATED)
|
||||
|
||||
# The document was created in the DB?
|
||||
self.assertEqual(Document.objects.count(), 1)
|
||||
|
||||
new_version_url = reverse(
|
||||
'document-new-version', args=[Document.objects.first().pk]
|
||||
)
|
||||
|
||||
with open(TEST_DOCUMENT_PATH) as file_descriptor:
|
||||
response = document_client.post(
|
||||
new_version_url, {'file': file_descriptor}
|
||||
)
|
||||
|
||||
# Make sure the document uploaded correctly
|
||||
document = Document.objects.first()
|
||||
|
||||
self.assertEqual(document.pk, document_data['id'])
|
||||
|
||||
self.assertEqual(document.versions.count(), 1)
|
||||
|
||||
self.assertEqual(document.exists(), True)
|
||||
self.assertEqual(document.size, 272213)
|
||||
|
||||
self.assertEqual(document.file_mimetype, 'application/pdf')
|
||||
self.assertEqual(document.file_mime_encoding, 'binary')
|
||||
self.assertEqual(document.label, TEST_SMALL_DOCUMENT_FILENAME)
|
||||
self.assertEqual(document.label, TEST_DOCUMENT_FILENAME)
|
||||
self.assertEqual(
|
||||
document.checksum,
|
||||
'c637ffab6b8bb026ed3784afdb07663fddc60099853fae2be93890852a69ecf3'
|
||||
)
|
||||
self.assertEqual(document.page_count, 47)
|
||||
|
||||
# Make sure we can edit the document via the API
|
||||
document_url = reverse(
|
||||
'document-detail', args=[Document.objects.first().pk]
|
||||
)
|
||||
def test_document_move_to_trash(self):
|
||||
with open(TEST_SMALL_DOCUMENT_PATH) as file_object:
|
||||
document = self.document_type.new_document(
|
||||
file_object=File(file_object),
|
||||
)
|
||||
|
||||
response = document_client.post(
|
||||
document_url, {'description': 'edited test document'}
|
||||
)
|
||||
self.client.delete(reverse('rest_api:document-detail', args=(document.pk,)))
|
||||
|
||||
# self.assertTrue(document.description, 'edited test document')
|
||||
|
||||
# Make sure we can delete the document via the API
|
||||
response = document_client.delete(document_url)
|
||||
|
||||
# The document was deleted from the the DB?
|
||||
self.assertEqual(Document.objects.count(), 0)
|
||||
self.assertEqual(Document.trash.count(), 1)
|
||||
|
||||
def test_deleted_document_delete_from_trash(self):
|
||||
with open(TEST_SMALL_DOCUMENT_PATH) as file_object:
|
||||
document = self.document_type.new_document(
|
||||
file_object=File(file_object),
|
||||
)
|
||||
|
||||
document.delete()
|
||||
|
||||
self.assertEqual(Document.objects.count(), 0)
|
||||
self.assertEqual(Document.trash.count(), 1)
|
||||
|
||||
self.client.delete(reverse('rest_api:deleteddocument-detail', args=(document.pk,)))
|
||||
|
||||
self.assertEqual(Document.trash.count(), 0)
|
||||
|
||||
def test_deleted_document_restore(self):
|
||||
with open(TEST_SMALL_DOCUMENT_PATH) as file_object:
|
||||
document = self.document_type.new_document(
|
||||
file_object=File(file_object),
|
||||
)
|
||||
|
||||
document.delete()
|
||||
|
||||
self.client.post(reverse('rest_api:deleteddocument-restore', args=(document.pk,)))
|
||||
|
||||
self.assertEqual(Document.trash.count(), 0)
|
||||
self.assertEqual(Document.objects.count(), 1)
|
||||
|
||||
def test_document_new_version_upload(self):
|
||||
with open(TEST_SMALL_DOCUMENT_PATH) as file_object:
|
||||
document = self.document_type.new_document(
|
||||
file_object=File(file_object),
|
||||
)
|
||||
|
||||
with open(TEST_DOCUMENT_PATH) as file_descriptor:
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
'rest_api:document-version-list', args=(document.pk,)
|
||||
), {
|
||||
'comment': '',
|
||||
'file': file_descriptor,
|
||||
}
|
||||
)
|
||||
print response
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED)
|
||||
|
||||
self.assertEqual(document.versions.count(), 2)
|
||||
self.assertEqual(document.exists(), True)
|
||||
self.assertEqual(document.size, 272213)
|
||||
self.assertEqual(document.file_mimetype, 'application/pdf')
|
||||
self.assertEqual(document.file_mime_encoding, 'binary')
|
||||
self.assertEqual(
|
||||
document.checksum,
|
||||
'c637ffab6b8bb026ed3784afdb07663fddc60099853fae2be93890852a69ecf3'
|
||||
)
|
||||
self.assertEqual(document.page_count, 47)
|
||||
|
||||
def test_document_version_revert(self):
|
||||
with open(TEST_SMALL_DOCUMENT_PATH) as file_object:
|
||||
document = self.document_type.new_document(
|
||||
file_object=File(file_object),
|
||||
)
|
||||
|
||||
with open(TEST_DOCUMENT_PATH) as file_object:
|
||||
document.new_version(file_object=File(file_object))
|
||||
|
||||
document_version = document.versions.first()
|
||||
|
||||
self.assertEqual(document.versions.count(), 2)
|
||||
|
||||
self.client.post(
|
||||
reverse(
|
||||
'rest_api:documentversion-revert', args=(document_version.pk,)
|
||||
)
|
||||
)
|
||||
|
||||
self.assertEqual(document.versions.count(), 1)
|
||||
|
||||
self.assertEqual(document_version, document.latest_version)
|
||||
|
||||
#def test_document_set_document_type(self):
|
||||
# pass
|
||||
|
||||
@@ -18,8 +18,9 @@ TEST_SMALL_DOCUMENT_FILENAME = 'title_page.png'
|
||||
TEST_MULTI_PAGE_TIFF = 'multi_page.tiff'
|
||||
TEST_NON_ASCII_DOCUMENT_FILENAME = 'I18N_title_áéíóúüñÑ.png'
|
||||
TEST_NON_ASCII_COMPRESSED_DOCUMENT_FILENAME = 'I18N_title_áéíóúüñÑ.png.zip'
|
||||
TEST_DOCUMENT_FILENAME = 'mayan_11_1.pdf'
|
||||
TEST_DOCUMENT_PATH = os.path.join(
|
||||
settings.BASE_DIR, 'contrib', 'sample_documents', 'mayan_11_1.pdf'
|
||||
settings.BASE_DIR, 'contrib', 'sample_documents', TEST_DOCUMENT_FILENAME
|
||||
)
|
||||
TEST_SMALL_DOCUMENT_PATH = os.path.join(
|
||||
settings.BASE_DIR, 'contrib', 'sample_documents',
|
||||
|
||||
@@ -3,10 +3,12 @@ from __future__ import unicode_literals
|
||||
from django.conf.urls import patterns, url
|
||||
|
||||
from .api_views import (
|
||||
APIDocumentView, APIDocumentImageView, APIDocumentListView,
|
||||
APIDocumentPageView, APIDocumentTypeDocumentListView,
|
||||
APIDocumentTypeListView, APIDocumentTypeView,
|
||||
APIDocumentVersionCreateView, APIDocumentVersionView,
|
||||
APIDeletedDocumentListView, APIDeletedDocumentRestoreView,
|
||||
APIDeletedDocumentView, APIDocumentView, APIDocumentListView,
|
||||
APIDocumentPageImageView, APIDocumentPageView,
|
||||
APIDocumentTypeDocumentListView, APIDocumentTypeListView,
|
||||
APIDocumentTypeView, APIDocumentVersionsListView,
|
||||
APIDocumentVersionRevertView, APIDocumentVersionView,
|
||||
APIRecentDocumentListView
|
||||
)
|
||||
from .settings import setting_print_size, setting_display_size
|
||||
@@ -229,6 +231,18 @@ urlpatterns = patterns(
|
||||
|
||||
api_urls = patterns(
|
||||
'',
|
||||
url(
|
||||
r'^deleted_documents/$', APIDeletedDocumentListView.as_view(),
|
||||
name='deleteddocument-list'
|
||||
),
|
||||
url(
|
||||
r'^deleted_documents/(?P<pk>[0-9]+)/$',
|
||||
APIDeletedDocumentView.as_view(), name='deleteddocument-detail'
|
||||
),
|
||||
url(
|
||||
r'^deleted_documents/(?P<pk>[0-9]+)/restore/$',
|
||||
APIDeletedDocumentRestoreView.as_view(), name='deleteddocument-restore'
|
||||
),
|
||||
url(r'^documents/$', APIDocumentListView.as_view(), name='document-list'),
|
||||
url(
|
||||
r'^documents/recent/$', APIRecentDocumentListView.as_view(),
|
||||
@@ -238,33 +252,37 @@ api_urls = patterns(
|
||||
r'^documents/(?P<pk>[0-9]+)/$', APIDocumentView.as_view(),
|
||||
name='document-detail'
|
||||
),
|
||||
url(
|
||||
r'^documents/(?P<pk>[0-9]+)/versions/$',
|
||||
APIDocumentVersionsListView.as_view(), name='document-version-list'
|
||||
),
|
||||
url(
|
||||
r'^document_version/(?P<pk>[0-9]+)/$',
|
||||
APIDocumentVersionView.as_view(), name='documentversion-detail'
|
||||
),
|
||||
url(
|
||||
r'^document_version/(?P<pk>[0-9]+)/revert/$',
|
||||
APIDocumentVersionRevertView.as_view(), name='documentversion-revert'
|
||||
),
|
||||
url(
|
||||
r'^document_page/(?P<pk>[0-9]+)/$', APIDocumentPageView.as_view(),
|
||||
name='documentpage-detail'
|
||||
),
|
||||
url(
|
||||
r'^documents/(?P<pk>[0-9]+)/image/$', APIDocumentImageView.as_view(),
|
||||
name='document-image'
|
||||
r'^document_page/(?P<pk>[0-9]+)/image/$',
|
||||
APIDocumentPageImageView.as_view(), name='documentpage-image'
|
||||
),
|
||||
url(
|
||||
r'^documents/(?P<pk>[0-9]+)/new_version/$',
|
||||
APIDocumentVersionCreateView.as_view(), name='document-new-version'
|
||||
),
|
||||
url(
|
||||
r'^documenttypes/(?P<pk>[0-9]+)/documents/$',
|
||||
r'^document_types/(?P<pk>[0-9]+)/documents/$',
|
||||
APIDocumentTypeDocumentListView.as_view(),
|
||||
name='documenttype-document-list'
|
||||
),
|
||||
url(
|
||||
r'^documenttypes/(?P<pk>[0-9]+)/$', APIDocumentTypeView.as_view(),
|
||||
r'^document_types/(?P<pk>[0-9]+)/$', APIDocumentTypeView.as_view(),
|
||||
name='documenttype-detail'
|
||||
),
|
||||
url(
|
||||
r'^documenttypes/$', APIDocumentTypeListView.as_view(),
|
||||
r'^document_types/$', APIDocumentTypeListView.as_view(),
|
||||
name='documenttype-list'
|
||||
),
|
||||
)
|
||||
|
||||
@@ -99,11 +99,12 @@ def document_html_widget(document_page, click_view=None, click_view_arguments=No
|
||||
|
||||
alt_text = _('Document page image')
|
||||
|
||||
if not document_page:
|
||||
return mark_safe('<span class="fa-stack fa-lg"><i class="fa fa-file-o fa-stack-2x"></i><i class="fa fa-question fa-stack-1x text-danger"></i></span>')
|
||||
|
||||
document = document_page.document
|
||||
page = document_page.page_number
|
||||
|
||||
query_dict = {
|
||||
'page': page,
|
||||
'zoom': zoom,
|
||||
'rotation': rotation,
|
||||
'size': size,
|
||||
@@ -117,12 +118,12 @@ def document_html_widget(document_page, click_view=None, click_view_arguments=No
|
||||
query_string = urlencode(query_dict)
|
||||
|
||||
preview_view = '%s?%s' % (
|
||||
reverse('document-image', args=[document.pk]), query_string
|
||||
reverse('rest_api:documentpage-image', args=[document_page.pk]), query_string
|
||||
)
|
||||
|
||||
result.append(
|
||||
'<div class="tc" id="document-%d-%d">' % (
|
||||
document.pk, page if page else 1
|
||||
document.pk, document_page.page_number if document_page.page_number else 1
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user