Add proper document creation API endpoint

This commit is contained in:
Roberto Rosario
2014-10-27 04:49:29 -04:00
parent 165d01610b
commit 9c9632f920
5 changed files with 135 additions and 11 deletions

View File

@@ -1,10 +1,13 @@
from __future__ import absolute_import
import tempfile
from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404
from rest_framework import generics, status
from rest_framework.response import Response
from rest_framework.settings import api_settings
from acls.models import AccessEntry
from converter.exceptions import UnkownConvertError, UnknownFileFormat
@@ -26,14 +29,15 @@ from .permissions import (PERMISSION_DOCUMENT_CREATE,
PERMISSION_DOCUMENT_TYPE_VIEW)
from .serializers import (DocumentImageSerializer, DocumentPageSerializer,
DocumentSerializer, DocumentTypeSerializer,
DocumentVersionSerializer)
DocumentVersionSerializer, NewDocumentSerializer)
from .settings import DISPLAY_SIZE, ZOOM_MAX_LEVEL, ZOOM_MIN_LEVEL
from .tasks import task_get_document_image
from .tasks import task_get_document_image, task_new_document
DOCUMENT_IMAGE_TASK_TIMEOUT = 10
class APIDocumentListView(generics.ListCreateAPIView):
class APIDocumentListView(generics.ListAPIView):
"""
Returns a list of all the documents.
"""
@@ -44,8 +48,51 @@ class APIDocumentListView(generics.ListCreateAPIView):
permission_classes = (MayanPermission,)
filter_backends = (MayanObjectPermissionsFilter,)
mayan_object_permissions = {'GET': [PERMISSION_DOCUMENT_VIEW]}
class APINewDocumentView(generics.GenericAPIView):
serializer_class = NewDocumentSerializer
permission_classes = (MayanPermission,)
mayan_view_permissions = {'POST': [PERMISSION_DOCUMENT_CREATE]}
def post(self, request, *args, **kwargs):
"""Create a new document."""
serializer = self.get_serializer(data=request.DATA, files=request.FILES)
if serializer.is_valid():
print serializer.data
temporary_file = tempfile.NamedTemporaryFile(delete=False)
source_file = request.FILES['file']
for chunk in source_file.chunks():
temporary_file.write(chunk)
temporary_file.close()
source_file.close()
task_new_document.apply_async(kwargs=dict(
file_path=temporary_file.name,
document_type_id=serializer.data['document_type'],
description=serializer.data['description'],
expand=serializer.data['expand'],
label=serializer.data['label'],
language=serializer.data['language'],
user_id=serializer.data['user']
), queue='uploads')
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_202_ACCEPTED,
headers=headers)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def get_success_headers(self, data):
try:
return {'Location': data[api_settings.URL_FIELD_NAME]}
except (TypeError, KeyError):
return {}
class APIDocumentView(generics.RetrieveUpdateDestroyAPIView):
"""

View File

@@ -1,11 +1,16 @@
from __future__ import absolute_import
from ast import literal_eval
import logging
from django.db import models, transaction
from common.compressed_files import CompressedFile, NotACompressedFile
from .settings import RECENT_COUNT
logger = logging.getLogger(__name__)
class DocumentPageTransformationManager(models.Manager):
def get_for_document_page(self, document_page):
@@ -54,9 +59,38 @@ class DocumentTypeManager(models.Manager):
class DocumentManager(models.Manager):
def new_document(self, document_type, file_object, label, command_line=False, description=None, expand=False, language=None, user=None):
documents_created = []
is_compressed = None
if expand:
try:
compressed_file = CompressedFile(file_object)
count = 1
for compressed_file_child in compressed_file.children():
if command_line:
print 'Uploading file #%d: %s' % (count, fp)
documents_created.append(self.upload_single_document(document_type=document_type, file_object=compressed_file_child, description=description, label=unicode(fp), language=language, user=user))
compressed_file_child.close()
count += 1
except NotACompressedFile:
is_compressed = False
logging.debug('Exception: NotACompressedFile')
if command_line:
raise
documents_created.append(self.upload_single_document(document_type=document_type, file_object=file_object, description=description, label=label, language=language, user=user))
else:
is_compressed = True
else:
documents_created.append(self.upload_single_document(document_type=document_type, file_object=file_object, description=description, label=label, language=language, user=user))
file_object.close()
return documents_created
@transaction.atomic
def new_document(self, file_object, document_type, label, user=None, description=None, language=None):
document = self.model(document_type=document_type, label=label,
description=description, language=language)
def upload_single_document(self, document_type, file_object, label, description=None, language=None, user=None):
document = self.model(description=description, document_type=document_type, language=language, label=label)
document.save(user=user)
return document.new_version(file=file_object, user=user)
document.new_version(file=file_object, user=user)
return document

View File

@@ -1,7 +1,10 @@
from __future__ import absolute_import
from django.contrib.auth.models import User
from rest_framework import serializers
from .literals import LANGUAGE_CHOICES
from .models import Document, DocumentVersion, DocumentPage, DocumentType
@@ -25,6 +28,7 @@ class DocumentImageSerializer(serializers.Serializer):
class DocumentSerializer(serializers.HyperlinkedModelSerializer):
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')
@@ -33,9 +37,20 @@ class DocumentSerializer(serializers.HyperlinkedModelSerializer):
model = Document
class DocumentTypeSerializer(serializers.HyperlinkedModelSerializer):
class DocumentTypeSerializer(serializers.ModelSerializer):
documents = serializers.HyperlinkedIdentityField(view_name='documenttype-document-list')
class Meta:
model = DocumentType
fields = ('id', 'url', 'name', 'documents')
fields = ('id', 'name', 'documents')
class NewDocumentSerializer(serializers.Serializer):
description = serializers.CharField(required=False)
document_type = DocumentTypeSerializer()
document_type = serializers.ChoiceField(choices=[(document_type.pk, document_type) for document_type in DocumentType.objects.all()])
expand = serializers.BooleanField(default=False)
file = serializers.FileField()
label = serializers.CharField()
language = serializers.ChoiceField(choices=LANGUAGE_CHOICES, blank_display_value=None, required=False)
user = serializers.ChoiceField(required=False, choices=[(user.pk, user) for user in User.objects.all()])

View File

@@ -1,8 +1,11 @@
import logging
from django.contrib.auth.models import User
from django.core.files import File
from mayan.celery import app
from .models import Document, DocumentVersion
from .models import Document, DocumentType, DocumentVersion
logger = logging.getLogger(__name__)
@@ -26,3 +29,26 @@ def task_clear_image_cache():
def task_update_page_count(version_id):
document_version = DocumentVersion.objects.get(pk=version_id)
document_version.update_page_count()
@app.task(ignore_result=True)
def task_new_document(document_type_id, file_path, label, description=None, expand=False, language=None, user_id=None):
document_type = DocumentType.objects.get(pk=document_type_id)
if user_id:
user = User.objects.get(pk=user_id)
else:
user = None
with File(file=open(file_path, mode='rb')) as file_object:
new_version = Document.objects.new_document(document_type=document_type, expand=expand, file_object=file_object, label=label, description=description, language=language, user=user)
# TODO: Report/record how was file uploaded
# if result['is_compressed'] is None:
# messages.success(request, _(u'File uploaded successfully.'))
# if result['is_compressed'] is True:
# messages.success(request, _(u'File uncompressed successfully and uploaded as individual files.'))
# if result['is_compressed'] is False:
# messages.warning(request, _(u'File was not a compressed file, uploaded as it was.'))

View File

@@ -5,7 +5,8 @@ from django.conf.urls import patterns, url
from .api_views import (APIDocumentView, APIDocumentImageView, APIDocumentListView,
APIDocumentPageView, APIDocumentTypeDocumentListView,
APIDocumentTypeListView, APIDocumentTypeView,
APIDocumentVersionCreateView, APIDocumentVersionView)
APIDocumentVersionCreateView, APIDocumentVersionView,
APINewDocumentView)
from .settings import PRINT_SIZE, DISPLAY_SIZE
from .views import DocumentListView
@@ -72,6 +73,7 @@ urlpatterns = patterns('documents.views',
api_urls = patterns('',
url(r'^documents/$', APIDocumentListView.as_view(), name='document-list'),
url(r'^documents/new/$', APINewDocumentView.as_view(), name='newdocument-view'),
url(r'^documents/(?P<pk>[0-9]+)/$', APIDocumentView.as_view(), name='document-detail'),
url(r'^document_version/(?P<pk>[0-9]+)/$', APIDocumentVersionView.as_view(), name='documentversion-detail'),
url(r'^document_page/(?P<pk>[0-9]+)/$', APIDocumentPageView.as_view(), name='documentpage-detail'),