diff --git a/apps/rest_api/__init__.py b/apps/rest_api/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/rest_api/models.py b/apps/rest_api/models.py new file mode 100644 index 0000000000..71a8362390 --- /dev/null +++ b/apps/rest_api/models.py @@ -0,0 +1,3 @@ +from django.db import models + +# Create your models here. diff --git a/apps/rest_api/resources.py b/apps/rest_api/resources.py new file mode 100644 index 0000000000..bbb8f52ebf --- /dev/null +++ b/apps/rest_api/resources.py @@ -0,0 +1,38 @@ +from django.core.urlresolvers import reverse + +from djangorestframework.resources import ModelResource + +from documents.models import Document +from converter.exceptions import UnknownFileFormat, UnkownConvertError + + +class DocumentResourceSimple(ModelResource): + model = Document + fields = ('url', 'pk', 'document_type', 'uuid', 'date_added', 'description', 'tags', 'comments', 'expensive_methods', 'files') + + def files(self, instance): + return [ + { + 'version': 1, + 'mimetype': instance.file_mimetype, + 'encoding': instance.file_mime_encoding, + 'filename': instance.get_fullname(), + 'date_updated': instance.date_updated, + 'checksum': instance.checksum, + 'size': instance.size, + 'exists': instance.exists(), + 'pages': [ + { + 'page_numer': page.page_number, + 'page_label': page.page_label, + #'content': + } + for page in instance.documentpage_set.all() + ] + } + ] + + def expensive_methods(self, instance): + return [ + {'is_zoomable': reverse('documents-expensive-is_zoomable', args=[instance.pk])}, + ] diff --git a/apps/rest_api/tests.py b/apps/rest_api/tests.py new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/apps/rest_api/tests.py @@ -0,0 +1 @@ + diff --git a/apps/rest_api/urls.py b/apps/rest_api/urls.py new file mode 100644 index 0000000000..b9eb0eea66 --- /dev/null +++ b/apps/rest_api/urls.py @@ -0,0 +1,18 @@ +from django.conf.urls.defaults import patterns, url + +from djangorestframework.views import ListModelView +from djangorestframework.views import ListOrCreateModelView, InstanceModelView + +from rest_api.views import APIBase, Version_0, ReadOnlyInstanceModelView, IsZoomable, Exists, Size +from rest_api.resources import DocumentResourceSimple + +urlpatterns = patterns('', + url(r'^$', APIBase.as_view(), name='api-root'), + url(r'^v0/$', Version_0.as_view(), name='api-version-0'), + + # Version 0 alpha API calls + url(r'^v0/document/(?P[0-9]+)/$', ReadOnlyInstanceModelView.as_view(resource=DocumentResourceSimple), name='documents-simple'), + url(r'^v0/document/(?P[0-9]+)/expensive/is_zoomable/$', IsZoomable.as_view(), name='documents-expensive-is_zoomable'), + url(r'^v0/document/(?P[0-9]+)/expensive/exists/$', IsZoomable.as_view(), name='documents-expensive-exists'), + url(r'^v0/document/(?P[0-9]+)/expensive/size/$', Size.as_view(), name='documents-expensive-size'), +) diff --git a/apps/rest_api/views.py b/apps/rest_api/views.py new file mode 100644 index 0000000000..06b5a46ce5 --- /dev/null +++ b/apps/rest_api/views.py @@ -0,0 +1,69 @@ +'''Views file for the rest_api app''' + +import logging + +from django.utils.translation import ugettext_lazy as _ +from django.shortcuts import get_object_or_404 +from django.core.urlresolvers import reverse + +from documents.models import Document +from converter.exceptions import UnknownFileFormat, UnkownConvertError + +from djangorestframework.views import View, ModelView, ListModelView, InstanceModelView +from djangorestframework.mixins import InstanceMixin, ReadModelMixin +from djangorestframework.response import Response +from djangorestframework import status + +logger = logging.getLogger(__name__) + + +class ReadOnlyInstanceModelView(InstanceModelView): + allowed_methods = ['GET'] + + +class APIBase(View): + """This is the REST API for Mayan EDMS (https://github.com/rosarior/mayan/). + + All the API calls can be navigated either through the browser or from the command line... + + bash: curl -X GET http://127.0.0.1:8000/api/ # (Use default renderer) + bash: curl -X GET http://127.0.0.1:8000/api/ -H 'Accept: text/plain' # (Use plaintext documentation renderer) + + """ + + def get(self, request): + return [ + {'name': 'Version 0 Alpha', 'url': reverse('api-version-0')} + ] + + +class Version_0(View): + def get(self, request): + return [ + {'name': 'Resources', 'resources': ['documents/']} + ] + + +class IsZoomable(View): + def get(self, request, pk): + logger.info('received is_zoomable call from: %s' % (request.META['REMOTE_ADDR'])) + document = get_object_or_404(Document, pk=pk) + try: + document.get_image_cache_name(1) # TODO: page + return {'result': True} + except (UnknownFileFormat, UnkownConvertError): + return {'result': False} + + +class Exists(View): + def get(self, request, pk): + logger.info('received exists call from: %s' % (request.META['REMOTE_ADDR'])) + document = get_object_or_404(Document, pk=pk) + return {'result': document.exists()} + + +class Size(View): + def get(self, request, pk): + logger.info('received size call from: %s' % (request.META['REMOTE_ADDR'])) + document = get_object_or_404(Document, pk=pk) + return {'result': document.size} diff --git a/requirements/development.txt b/requirements/development.txt index fe228d3604..e48c037891 100644 --- a/requirements/development.txt +++ b/requirements/development.txt @@ -19,3 +19,4 @@ Pillow==1.7.4 cssmin==0.1.4 django-compressor==1.1 -e git://github.com/rosarior/django-sendfile.git#egg=django-sendfile +djangorestframework==0.2.3 diff --git a/requirements/production.txt b/requirements/production.txt index 39948f87ba..dd976f27a7 100644 --- a/requirements/production.txt +++ b/requirements/production.txt @@ -16,3 +16,4 @@ Pillow==1.7.4 cssmin==0.1.4 django-compressor==1.1 -e git://github.com/rosarior/django-sendfile.git#egg=django-sendfile +djangorestframework==0.2.3 diff --git a/settings.py b/settings.py index ea37f7cbf0..5c025e3fc4 100644 --- a/settings.py +++ b/settings.py @@ -81,7 +81,8 @@ STATIC_URL = '/%s-static/' % PROJECT_NAME # URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a # trailing slash. # Examples: "http://foo.com/media/", "/media/". -ADMIN_MEDIA_PREFIX = STATIC_URL + 'grappelli/' +#ADMIN_MEDIA_PREFIX = STATIC_URL + 'grappelli/' +ADMIN_MEDIA_PREFIX = STATIC_URL + 'admin/' # Make this unique, and don't share it with anybody. SECRET_KEY = 'om^a(i8^6&h+umbd2%pt91cj!qu_@oztw117rgxmn(n2lp^*c!' @@ -117,7 +118,7 @@ TEMPLATE_DIRS = ( ) INSTALLED_APPS = ( - 'grappelli', + #'grappelli', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', @@ -164,6 +165,8 @@ INSTALLED_APPS = ( 'history', 'main', 'compressor', + 'djangorestframework', + 'rest_api', ) TEMPLATE_CONTEXT_PROCESSORS = ( @@ -286,7 +289,7 @@ CELERY_DISABLE_RATE_LIMITS = True #--------- Web theme --------------- WEB_THEME_ENABLE_SCROLL_JS = False #--------- Grappelli ---------------- -GRAPPELLI_ADMIN_TITLE = PROJECT_TITLE +#GRAPPELLI_ADMIN_TITLE = PROJECT_TITLE #--------- Django ------------------- LOGIN_URL = '/login/' LOGIN_REDIRECT_URL = '/' diff --git a/urls.py b/urls.py index 4736d4d377..e23e774472 100644 --- a/urls.py +++ b/urls.py @@ -15,7 +15,7 @@ urlpatterns = patterns('', (r'^tags/', include('tags.urls')), (r'^admin/doc/', include('django.contrib.admindocs.urls')), (r'^admin/', include(admin.site.urls)), - (r'^grappelli/', include('grappelli.urls')), + #(r'^grappelli/', include('grappelli.urls')), (r'^sentry/', include('sentry.urls')), (r'^comments/', include('document_comments.urls')), (r'^user_management/', include('user_management.urls')), @@ -28,6 +28,7 @@ urlpatterns = patterns('', (r'^sources/', include('sources.urls')), (r'^project_setup/', include('project_setup.urls')), (r'^project_tools/', include('project_tools.urls')), + (r'^api/', include('rest_api.urls')), )