You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2017/09/14 14:21:29 UTC

[4/4] airavata-django-portal git commit: Using ViewSet for project REST API mappings

Using ViewSet for project REST API mappings


Project: http://git-wip-us.apache.org/repos/asf/airavata-django-portal/repo
Commit: http://git-wip-us.apache.org/repos/asf/airavata-django-portal/commit/4253233f
Tree: http://git-wip-us.apache.org/repos/asf/airavata-django-portal/tree/4253233f
Diff: http://git-wip-us.apache.org/repos/asf/airavata-django-portal/diff/4253233f

Branch: refs/heads/master
Commit: 4253233ffe87928781cde0da90f1c2c8aa361e9e
Parents: c10a85d
Author: Marcus Christie <ma...@iu.edu>
Authored: Thu Sep 14 10:21:09 2017 -0400
Committer: Marcus Christie <ma...@iu.edu>
Committed: Thu Sep 14 10:21:09 2017 -0400

----------------------------------------------------------------------
 django_airavata/apps/api/serializers.py |   7 +-
 django_airavata/apps/api/urls.py        |  11 ++-
 django_airavata/apps/api/views.py       | 110 +++++++++++++++++++--------
 django_airavata/apps/workspace/views.py |   2 +-
 4 files changed, 92 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/4253233f/django_airavata/apps/api/serializers.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/api/serializers.py b/django_airavata/apps/api/serializers.py
index 4a56838..d13b718 100644
--- a/django_airavata/apps/api/serializers.py
+++ b/django_airavata/apps/api/serializers.py
@@ -42,6 +42,7 @@ class GatewayIdDefaultField(serializers.CharField):
         self.default = settings.GATEWAY_ID
 
 class ProjectSerializer(serializers.Serializer):
+    url = FullyEncodedHyperlinkedIdentityField(view_name='project-detail', lookup_field='projectID', lookup_url_kwarg='pk')
     projectID = serializers.CharField(read_only=True)
     name = serializers.CharField(required=True)
     description = serializers.CharField(required=False)
@@ -53,7 +54,9 @@ class ProjectSerializer(serializers.Serializer):
         return Project(**validated_data)
 
     def update(self, instance, validated_data):
-        raise Exception("Not implemented")
+        instance.name = validated_data.get('name', instance.name)
+        instance.description = validated_data.get('description', instance.description)
+        return instance
 
     def get_username(self):
         return self.context.request.user.username
@@ -62,7 +65,7 @@ class ExperimentSerializer(serializers.Serializer):
 
     experimentId = serializers.CharField(read_only=True)
     projectId = serializers.CharField(required=True)
-    project = FullyEncodedHyperlinkedIdentityField(view_name='api_project_detail', lookup_field='projectId', lookup_url_kwarg='project_id')
+    project = FullyEncodedHyperlinkedIdentityField(view_name='project-detail', lookup_field='projectId', lookup_url_kwarg='project_id')
     gatewayId = GatewayIdDefaultField()
     experimentType = serializers.CharField(required=True)
     userName = GatewayUsernameDefaultField()

http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/4253233f/django_airavata/apps/api/urls.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/api/urls.py b/django_airavata/apps/api/urls.py
index 9cd7d75..544c07b 100644
--- a/django_airavata/apps/api/urls.py
+++ b/django_airavata/apps/api/urls.py
@@ -1,17 +1,22 @@
 
 from . import views
 
-from django.conf.urls import url
+from django.conf.urls import include, url
+from rest_framework import routers
 from rest_framework.urlpatterns import format_suffix_patterns
 
+router = routers.SimpleRouter()
+router.register(r'projects', views.ProjectViewSet, base_name='project')
+
 urlpatterns = [
     url(r'^$', views.api_root),
-    url(r'^projects/$', views.ProjectList.as_view(), name='api_project_list'),
+    # url(r'^projects/$', views.ProjectList.as_view(), name='api_project_list'),
     # More specific, longer URLs should come before less specific, shorter ones
     # since the regular expression for project_id allows any character, even '/'
     url(r'^projects/(?P<project_id>.+)/experiments/$', views.ProjectExperimentList.as_view(), name='api_project_experiments_list'),
-    url(r'^projects/(?P<project_id>.+)/$', views.ProjectDetail.as_view(), name='api_project_detail'),
+    # url(r'^projects/(?P<project_id>.+)/$', views.ProjectDetail.as_view(), name='api_project_detail'),
     url(r'^experiments/$', views.ExperimentList.as_view(), name='api_experiment_list'),
+    url(r'^', include(router.urls)),
 ]
 
 urlpatterns = format_suffix_patterns(urlpatterns)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/4253233f/django_airavata/apps/api/views.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/api/views.py b/django_airavata/apps/api/views.py
index 0d0a052..2de3ba8 100644
--- a/django_airavata/apps/api/views.py
+++ b/django_airavata/apps/api/views.py
@@ -1,14 +1,15 @@
 
 from . import serializers
 
-from rest_framework import status
+from rest_framework import status, mixins
 from rest_framework.decorators import api_view
 from rest_framework.views import APIView
+from rest_framework.viewsets import GenericViewSet
 from rest_framework.response import Response
 from rest_framework.reverse import reverse
 
 from django.conf import settings
-from django.http import JsonResponse
+from django.http import JsonResponse, Http404
 from django.shortcuts import render
 from django.views.decorators.csrf import csrf_exempt
 
@@ -16,42 +17,87 @@ from django.views.decorators.csrf import csrf_exempt
 @api_view(['GET'])
 def api_root(request, format=None):
     return Response({
-        'projects': reverse('api_project_list', request=request, format=format),
+        'projects': reverse('project-list', request=request, format=format),
         'experiments': reverse('api_experiment_list', request=request, format=format)
     })
 
-class ProjectList(APIView):
-    def get(self, request, format=None):
-        gateway_id = settings.GATEWAY_ID
-        username = request.user.username
+class GenericAPIBackedViewSet(GenericViewSet):
 
-        projects = request.airavata_client.getUserProjects(request.authz_token, gateway_id, username, -1, 0)
-        serializer = serializers.ProjectSerializer(projects, many=True, context={'request': request})
-        return Response(serializer.data)
+    def get_list(self):
+        """
+        Subclasses must implement.
+        """
+        raise NotImplementedError()
 
-    def post(self, request, format=None):
-        gateway_id = settings.GATEWAY_ID
-        username = request.user.username
-        serializer = serializers.ProjectSerializer(data=request.data, context={'request': request})
-        if serializer.is_valid():
-            project = serializer.create(serializer.validated_data)
-            project_id = request.airavata_client.createProject(request.authz_token, gateway_id, project)
-            project.projectID = project_id
-            serializer = serializers.ProjectSerializer(project, context={'request': request})
-            return Response(serializer.data, status=status.HTTP_201_CREATED)
-        else:
-            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
-
-class ProjectDetail(APIView):
-    def get(self, request, project_id, format=None):
-        gateway_id = settings.GATEWAY_ID
-        username = request.user.username
+    def get_instance(self, lookup_value):
+        """
+        Subclasses must implement.
+        """
+        raise NotImplementedError()
+
+    def get_queryset(self):
+        return self.get_list()
+
+    def get_object(self):
+        lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
+        lookup_value = self.kwargs[lookup_url_kwarg]
+        inst = self.get_instance(lookup_value)
+        if inst is None:
+            raise Http404
+        self.check_object_permissions(self.request, inst)
+        return inst
+
+    @property
+    def username(self):
+        return self.request.user.username
+
+    @property
+    def gateway_id(self):
+        return settings.GATEWAY_ID
+
+    @property
+    def authz_token(self):
+        return self.request.authz_token
+
+class CreateUpdateRetrieveListViewSet(mixins.CreateModelMixin,
+                                      mixins.RetrieveModelMixin,
+                                      mixins.UpdateModelMixin,
+                                      mixins.DestroyModelMixin,
+                                      mixins.ListModelMixin,
+                                      GenericAPIBackedViewSet):
+    """
+    A viewset that provides default `create()`, `retrieve()`, `update()`,
+    `partial_update()` and `list()` actions.
+
+    Subclasses must implement the following:
+    * get_list(self)
+    * get_instance(self, lookup_value)
+    * perform_create(self, serializer) - should return instance with id populated
+    * perform_update(self, serializer)
+    """
+    pass
+
+
+class ProjectViewSet(CreateUpdateRetrieveListViewSet):
+
+    serializer_class = serializers.ProjectSerializer
+
+    def get_list(self):
+        # TODO: support pagination
+        return self.request.airavata_client.getUserProjects(self.authz_token, self.gateway_id, self.username, -1, 0)
+
+    def get_instance(self, lookup_value):
+        return self.request.airavata_client.getProject(self.authz_token, lookup_value)
+
+    def perform_create(self, serializer):
+        project = serializer.save()
+        project_id = self.request.airavata_client.createProject(self.authz_token, self.gateway_id, project)
+        project.projectID = project_id
+
+    def perform_update(self, serializer):
+        project = serializer.save()
+        self.request.airavata_client.updateProject(self.authz_token, project.projectID, project)
 
-        print(project_id)
-        project = request.airavata_client.getProject(request.authz_token, project_id)
-        serializer = serializers.ProjectSerializer(project, context={'request': request})
-        return Response(serializer.data)
-    # TODO: add project update (PUT)
 
 class ExperimentList(APIView):
     def get(self, request, format=None):

http://git-wip-us.apache.org/repos/asf/airavata-django-portal/blob/4253233f/django_airavata/apps/workspace/views.py
----------------------------------------------------------------------
diff --git a/django_airavata/apps/workspace/views.py b/django_airavata/apps/workspace/views.py
index 4e8b4bd..6967f25 100644
--- a/django_airavata/apps/workspace/views.py
+++ b/django_airavata/apps/workspace/views.py
@@ -1,5 +1,5 @@
 
-from django_airavata.apps.api.views import ProjectList
+from django_airavata.apps.api.views import ProjectViewSet
 from rest_framework.renderers import JSONRenderer
 from django.conf import settings
 from django.contrib.auth.decorators import login_required