blob: a50b06424e5825fbfb88a318b1408fd8386a8359 [file] [log] [blame]
Scott Baker03696ee2015-01-11 13:45:19 -08001from rest_framework import generics
Scott Bakere791dc62014-08-28 14:02:54 -07002from rest_framework import serializers
Scott Baker03696ee2015-01-11 13:45:19 -08003from rest_framework.response import Response
4from rest_framework import status
Scott Bakere791dc62014-08-28 14:02:54 -07005
6""" PlusSerializerMixin
7
8 Implements Serializer fields that are common to all OpenCloud objects. For
9 example, stuff related to backend fields.
10"""
11
12class 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}
Scott Bakere5e44eb2014-12-23 11:04:27 -080019 # Rest_framework 3.0 uses _declared_fields instead of base_fields
20 _declared_fields = {"backendIcon": backendIcon, "backendHtml": backendHtml}
Scott Bakere791dc62014-08-28 14:02:54 -070021
22 def getBackendIcon(self, obj):
23 return obj.getBackendIcon()
24
25 def getBackendHtml(self, obj):
26 return obj.getBackendHtml()
27
Scott Baker77eba942015-01-12 12:57:22 -080028# XXX this was lifted and hacked up a bit from genapi.py
29class 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()",
35 "reasons": serializer.errors}
36 return Response(response, status=status.HTTP_400_BAD_REQUEST)
Scott Bakerbd46a922015-02-03 15:02:17 -080037
38 # now do XOS can_update permission checking
39
Scott Baker77eba942015-01-12 12:57:22 -080040 obj = serializer.object
41 obj.caller = request.user
Scott Bakerce7fc0a2015-02-03 14:47:08 -080042 if not obj.can_update(request.user):
Scott Bakerbd46a922015-02-03 15:02:17 -080043 response = {"error": "validation",
44 "specific_error": "failed can_update",
45 "reasons": []}
46 return Response(response, status=status.HTTP_400_BAD_REQUEST)
Scott Baker77eba942015-01-12 12:57:22 -080047
Scott Bakerbd46a922015-02-03 15:02:17 -080048 # stuff below is from generics.ListCreateAPIView
Scott Baker77eba942015-01-12 12:57:22 -080049
Scott Bakerbd46a922015-02-03 15:02:17 -080050 if (hasattr(self, "pre_save")):
51 # rest_framework 2.x
52 self.pre_save(serializer.object)
53 self.object = serializer.save(force_insert=True)
54 self.post_save(self.object, created=True)
55 else:
56 # rest_framework 3.x
57 self.perform_create(serializer)
58
59 headers = self.get_success_headers(serializer.data)
60 return Response(serializer.data, status=status.HTTP_201_CREATED,
61 headers=headers)
Scott Baker77eba942015-01-12 12:57:22 -080062
Scott Baker03696ee2015-01-11 13:45:19 -080063# XXX this is taken from genapi.py
64# XXX find a better way to re-use the code
65class PlusRetrieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
66
67 # To handle fine-grained field permissions, we have to check can_update
68 # the object has been updated but before it has been saved.
69
70 def update(self, request, *args, **kwargs):
71 partial = kwargs.pop('partial', False)
72 self.object = self.get_object_or_none()
73
74 serializer = self.get_serializer(self.object, data=request.DATA,
75 files=request.FILES, partial=partial)
76
77 if not serializer.is_valid():
78 response = {"error": "validation",
79 "specific_error": "not serializer.is_valid()",
80 "reasons": serializer.errors}
81 return Response(response, status=status.HTTP_400_BAD_REQUEST)
82
83 try:
84 self.pre_save(serializer.object)
85 except ValidationError as err:
86 # full_clean on model instance may be called in pre_save,
87 # so we have to handle eventual errors.
88 response = {"error": "validation",
89 "specific_error": "ValidationError in pre_save",
90 "reasons": err.message_dict}
91 return Response(response, status=status.HTTP_400_BAD_REQUEST)
92
93 if serializer.object is not None:
94 if not serializer.object.can_update(request.user):
95 return Response(status=status.HTTP_400_BAD_REQUEST)
96
97 if self.object is None:
Scott Bakerbd46a922015-02-03 15:02:17 -080098 raise Exception("Use the List API for creating objects")
Scott Baker03696ee2015-01-11 13:45:19 -080099
100 self.object = serializer.save(force_update=True)
Scott Bakerce7fc0a2015-02-03 14:47:08 -0800101 self.object.caller = request.user
Scott Baker03696ee2015-01-11 13:45:19 -0800102 self.post_save(self.object, created=False)
103 return Response(serializer.data, status=status.HTTP_200_OK)
104
105 def destroy(self, request, *args, **kwargs):
106 obj = self.get_object()
107 if obj.can_update(request.user):
108 return super(generics.RetrieveUpdateDestroyAPIView, self).destroy(request, *args, **kwargs)
109 else:
110 return Response(status=status.HTTP_400_BAD_REQUEST)
111