base class stuff for xoslib methods from genapi
[plstackapi.git] / planetstack / core / xoslib / methods / plus.py
1 from rest_framework import generics
2 from rest_framework import serializers
3 from rest_framework.response import Response
4 from rest_framework import status
5
6 """ PlusSerializerMixin
7
8     Implements Serializer fields that are common to all OpenCloud objects. For
9     example, stuff related to backend fields.
10 """
11 \r
12 class PlusSerializerMixin():
13     backendIcon = serializers.SerializerMethodField("getBackendIcon")
14     backendHtml = serializers.SerializerMethodField("getBackendHtml")
15
16     # This will cause a descendant class to pull in the methods defined
17     # above. See rest_framework/serializers.py: _get_declared_fields().
18     base_fields = {"backendIcon": backendIcon, "backendHtml": backendHtml}
19     # Rest_framework 3.0 uses _declared_fields instead of base_fields
20     _declared_fields = {"backendIcon": backendIcon, "backendHtml": backendHtml}
21
22     def getBackendIcon(self, obj):
23         return obj.getBackendIcon()
24
25     def getBackendHtml(self, obj):
26         return obj.getBackendHtml()
27
28 # XXX this was lifted and hacked up a bit from genapi.py
29 class PlusListCreateAPIView(generics.ListCreateAPIView):
30     def create(self, request, *args, **kwargs):
31         serializer = self.get_serializer(data=request.DATA, files=request.FILES)
32         if not (serializer.is_valid()):
33             response = {"error": "validation",
34                         "specific_error": "not serializer.is_valid()",\r
35                         "reasons": serializer.errors}\r
36             return Response(response, status=status.HTTP_400_BAD_REQUEST)
37         obj = serializer.object
38         obj.caller = request.user
39         if obj.can_update(request.user):
40             return super(PlusListCreateAPIView, self).create(request, *args, **kwargs)
41         else:
42             raise Exception("failed obj.can_update")
43
44         ret = super(PlusListCreateAPIView, self).create(request, *args, **kwargs)
45         if (ret.status_code%100 != 200):
46             raise Exception(ret.data)
47
48         return ret
49
50 # XXX this is taken from genapi.py
51 # XXX find a better way to re-use the code
52 class PlusRetrieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
53
54     # To handle fine-grained field permissions, we have to check can_update
55     # the object has been updated but before it has been saved.
56
57     def update(self, request, *args, **kwargs):\r
58         partial = kwargs.pop('partial', False)\r
59         self.object = self.get_object_or_none()\r
60 \r
61         serializer = self.get_serializer(self.object, data=request.DATA,\r
62                                          files=request.FILES, partial=partial)\r
63 \r
64         if not serializer.is_valid():\r
65             response = {"error": "validation",\r
66                         "specific_error": "not serializer.is_valid()",\r
67                         "reasons": serializer.errors}\r
68             return Response(response, status=status.HTTP_400_BAD_REQUEST)\r
69 \r
70         try:\r
71             self.pre_save(serializer.object)\r
72         except ValidationError as err:\r
73             # full_clean on model instance may be called in pre_save,\r
74             # so we have to handle eventual errors.\r
75             response = {"error": "validation",\r
76                          "specific_error": "ValidationError in pre_save",\r
77                          "reasons": err.message_dict}\r
78             return Response(response, status=status.HTTP_400_BAD_REQUEST)\r
79 \r
80         if serializer.object is not None:\r
81             if not serializer.object.can_update(request.user):\r
82                 return Response(status=status.HTTP_400_BAD_REQUEST)\r
83 \r
84         if self.object is None:\r
85             self.object = serializer.save(force_insert=True)\r
86             self.post_save(self.object, created=True)\r
87             return Response(serializer.data, status=status.HTTP_201_CREATED)\r
88 \r
89         self.object = serializer.save(force_update=True)\r
90         self.post_save(self.object, created=False)\r
91         return Response(serializer.data, status=status.HTTP_200_OK)
92
93     def destroy(self, request, *args, **kwargs):
94         obj = self.get_object()
95         if obj.can_update(request.user):
96             return super(generics.RetrieveUpdateDestroyAPIView, self).destroy(request, *args, **kwargs)
97         else:
98             return Response(status=status.HTTP_400_BAD_REQUEST)
99