Commit 0029c079 by Oleg Marshev

Use cors and refactor.

parent 6e9d2a7b
from django.conf.urls import patterns, url, include
urlpatterns = patterns(
'',
url(r'^v1/', include('notesapi.v1.urls', namespace='v0')),
)
from django.conf.urls import patterns, url, include
from notesapi.v1.views import AnnotationListView, AnnotationDetailView, AnnotationSearchView
urlpatterns = patterns('', # nopep8
url(r'^annotations$', AnnotationListView.as_view(), name='annotations'),
url(r'^annotations/(?P<annotation_id>[a-zA-Z0-9_-]+)$', AnnotationDetailView.as_view(), name='annotations_detail'),
url(r'^search$', AnnotationSearchView.as_view(), name='annotations_search')
)
import requests
import json
from django.http import HttpResponse
from django.conf import settings
from django.core.urlresolvers import reverse
from rest_framework import status
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.decorators import api_view, permission_classes
from annotator.annotation import Annotation
from annotator.atoi import atoi
CREATE_FILTER_FIELDS = ('updated', 'created', 'consumer', 'id')
UPDATE_FILTER_FIELDS = ('updated', 'created', 'user', 'consumer')
class AnnotationSearchView(APIView):
"""
Search annotations.
"""
permission_classes = (AllowAny,)
def get(self, request, *args, **kwargs):
"""
Search annotations.
This method supports the limit and offset query parameters for paging through results.
"""
params = request.QUERY_PARAMS
if 'offset' in params:
kwargs['offset'] = atoi(params.pop('offset'), default=None)
if 'limit' in params:
kwargs['limit'] = atoi(params.pop('limit'), default=None)
# All remaining parameters are considered searched fields.
kwargs['query'] = params
results = Annotation.search(**kwargs)
total = Annotation.count(**kwargs)
return Response({'total': total, 'rows': results})
class AnnotationListView(APIView):
"""
List all annotations or create.
"""
permission_classes = (AllowAny,)
def get(self, request):
"""
Get a list of all annotations.
"""
# TODO: get user.
user = None
annotations = Annotation.search(user)
return Response(annotations)
def post(self, request, *args, **kwargs):
"""
Create a new annotation.
"""
if request.DATA is not None:
annotation = Annotation(_filter_input(request.DATA, CREATE_FILTER_FIELDS))
refresh = self.kwargs.get('refresh') != 'false'
annotation.save(refresh=refresh)
location = reverse('api:v0:annotations_detail', kwargs={'annotation_id': annotation['id']})
return Response(annotation, status=status.HTTP_201_CREATED, headers={'Location': location})
class AnnotationDetailView(APIView):
"""
Annotation detail view.
"""
permission_classes = (AllowAny,)
UPDATE_FILTER_FIELDS = ('updated', 'created', 'user', 'consumer')
def get(self, request, *args, **kwargs):
"""
Get an existing annotation.
"""
annotation_id = self.kwargs.get('annotation_id')
annotation = Annotation.fetch(annotation_id)
if not annotation:
return Response(annotation, status=status.HTTP_404_NOT_FOUND)
return Response(annotation)
def put(self, request, *args, **kwargs):
"""
Update an existing annotation.
"""
annotation_id = self.kwargs.get('annotation_id')
annotation = Annotation.fetch(annotation_id)
if not annotation:
return Response('Annotation not found! No update performed.', status=status.HTTP_404_NOT_FOUND)
if request.DATA is not None:
updated = _filter_input(request.DATA, UPDATE_FILTER_FIELDS)
updated['id'] = annotation_id # use id from URL, regardless of what arrives in JSON payload.
annotation.update(updated)
refresh = self.kwargs.get('refresh') != 'false'
annotation.save(refresh=refresh)
return Response(annotation)
def delete(self, request, *args, **kwargs):
"""
Delete an annotation.
"""
annotation_id = self.kwargs.get('annotation_id')
annotation = Annotation.fetch(annotation_id)
if not annotation:
return Response('Annotation not found! No delete performed.', status=status.HTTP_404_NOT_FOUND)
annotation.delete()
# Annotation deleted successfully.
return Response(status=status.HTTP_204_NO_CONTENT)
def _filter_input(annotation, fields):
for field in fields:
annotation.pop(field, None)
return annotation
def _convert_str(value, default=0):
try:
return int(v or default)
except ValueError:
return default
ROOT_URLCONF = 'notesserver.urls' ROOT_URLCONF = 'notesserver.urls'
MIDDLEWARE_CLASSES = ( MIDDLEWARE_CLASSES = (
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware', 'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware' 'django.middleware.csrf.CsrfViewMiddleware',
) )
INSTALLED_APPS = ( INSTALLED_APPS = (
'django.contrib.staticfiles', 'django.contrib.staticfiles',
'rest_framework', 'rest_framework',
'rest_framework_swagger', 'rest_framework_swagger',
'corsheaders',
) )
STATIC_URL = '/static/' STATIC_URL = '/static/'
...@@ -20,3 +22,5 @@ REST_FRAMEWORK = { ...@@ -20,3 +22,5 @@ REST_FRAMEWORK = {
} }
WSGI_APPLICATION = 'notesserver.wsgi.application' WSGI_APPLICATION = 'notesserver.wsgi.application'
CORS_ORIGIN_ALLOW_ALL = True
from .common import * from .common import *
SECRET_KEY = 'fkjsdfkjsdhflhdlfhs;lfoefh' SECRET_KEY = 'secret_key'
DEBUG = True DEBUG = True
ANNOTATOR_STORE = "http://0.0.0.0:5002/"
from django.conf.urls import patterns, url from django.conf.urls import patterns, url, include
from notesserver.views import StatusView, AnnotationListView, AnnotationDetailView from notesserver.views import StatusView
urlpatterns = patterns('', # nopep8 urlpatterns = patterns('', # nopep8
url(r'^status/$', StatusView.as_view(), name='status'), url(r'^status/$', StatusView.as_view(), name='status'),
url(r'^$', 'notesserver.views.root', name='root'), url(r'^$', 'notesserver.views.root', name='root'),
url(r'^annotations/$', AnnotationListView.as_view(), name='annotations'), url(r'^api/', include('notesapi.urls', namespace='api')),
url(r'^annotations/(?P<annotation_id>[a-zA-Z0-9_-]+)$', AnnotationDetailView.as_view(), name='annotations_detail')
) )
...@@ -10,11 +10,6 @@ from rest_framework.response import Response ...@@ -10,11 +10,6 @@ from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from rest_framework.decorators import api_view, permission_classes from rest_framework.decorators import api_view, permission_classes
from annotator.elasticsearch import ElasticSearch
from annotator.annotation import Annotation
CREATE_FILTER_FIELDS = ('updated', 'created', 'consumer', 'id')
UPDATE_FILTER_FIELDS = ('updated', 'created', 'user', 'consumer')
@api_view(['GET']) @api_view(['GET'])
@permission_classes([AllowAny]) @permission_classes([AllowAny])
...@@ -22,7 +17,10 @@ def root(request): ...@@ -22,7 +17,10 @@ def root(request):
""" """
Root view. Root view.
""" """
return Response({}) return Response({
"name": "edX Notes API",
"version": "1"
})
class StatusView(APIView): class StatusView(APIView):
...@@ -35,103 +33,4 @@ class StatusView(APIView): ...@@ -35,103 +33,4 @@ class StatusView(APIView):
""" """
Service status. Service status.
""" """
return Response({}) return Response()
class AnnotationListView(APIView):
"""
List all annotations or create.
"""
permission_classes = (AllowAny,)
def get(self, request):
"""
"""
# TODO: get user.
user = None
conn = ElasticSearch()
annotations = Annotation.search(user)
return Response(annotations)
def post(self, request, *args, **kwargs):
"""
Create a new annotation.
"""
conn = ElasticSearch()
if request.DATA is not None:
annotation = Annotation(_filter_input(request.DATA, CREATE_FILTER_FIELDS))
refresh = self.kwargs.get('refresh') != 'false'
annotation.save(refresh=refresh)
location = reverse('annotations_detail', kwargs={'annotation_id': annotation['id']})
return Response(annotation, status=status.HTTP_201_CREATED, headers={'Location': location})
class AnnotationDetailView(APIView):
"""
Annotation detail view.
"""
permission_classes = (AllowAny,)
UPDATE_FILTER_FIELDS = ('updated', 'created', 'user', 'consumer')
def get(self, request, *args, **kwargs):
"""
Get an existing annotation.
"""
annotation_id = self.kwargs.get('annotation_id')
annotation = Annotation.fetch(annotation_id)
if not annotation:
return Response(annotation, status=status.HTTP_404_NOT_FOUND)
return Response(annotation)
def put(self, request, *args, **kwargs):
"""
Update an existing annotation.
"""
annotation_id = self.kwargs.get('annotation_id')
annotation = Annotation.fetch(annotation_id)
if not annotation:
return Response('Annotation not found! No update performed.', status=status.HTTP_404_NOT_FOUND)
if request.DATA is not None:
updated = _filter_input(request.DATA, UPDATE_FILTER_FIELDS)
updated['id'] = annotation_id # use id from URL, regardless of what arrives in JSON payload.
annotation.update(updated)
refresh = self.kwargs.get('refresh') != 'false'
annotation.save(refresh=refresh)
return Response(annotation)
def delete(self, request, *args, **kwargs):
"""
Delete an annotation.
"""
annotation_id = self.kwargs.get('annotation_id')
annotation = Annotation.fetch(annotation_id)
if not annotation:
return Response('Annotation not found! No delete performed.', status=status.HTTP_404_NOT_FOUND)
annotation.delete()
# Annotation deleted successfully.
return Response(status=status.HTTP_204_NO_CONTENT)
def _filter_input(annotation, fields):
for field in fields:
annotation.pop(field, None)
return annotation
...@@ -3,3 +3,4 @@ djangorestframework==2.4.4 ...@@ -3,3 +3,4 @@ djangorestframework==2.4.4
django-rest-swagger==0.2.0 django-rest-swagger==0.2.0
elasticsearch==1.2.0 elasticsearch==1.2.0
annotator==0.12.0 annotator==0.12.0
django-cors-headers==0.13
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment