22from django .db .models .manager import BaseManager
33from rest_framework import generics
44from rest_framework .response import Response
5- from rest_framework .exceptions import NotFound
5+ from rest_framework .exceptions import NotFound , MethodNotAllowed
66
7+ from rest_framework_json_api .exceptions import Conflict
78from rest_framework_json_api .serializers import ResourceIdentifierObjectSerializer
89from rest_framework_json_api .utils import format_relation_name , get_resource_type_from_instance
910
@@ -18,19 +19,57 @@ def get(self, request, *args, **kwargs):
1819
1920 def patch (self , request , * args , ** kwargs ):
2021 parent_obj = self .get_object ()
21- if hasattr (parent_obj , kwargs ['related_field' ]):
22- related_model_class = self .get_related_instance ().__class__
22+ related_instance_or_manager = self .get_related_instance ()
23+
24+ if isinstance (related_instance_or_manager , BaseManager ):
25+ related_model_class = related_instance_or_manager .model
26+ serializer = self .get_serializer (data = request .data , model_class = related_model_class , many = True )
27+ serializer .is_valid (raise_exception = True )
28+ related_instance_or_manager .all ().delete ()
29+ related_instance_or_manager .add (* serializer .validated_data )
30+ else :
31+ related_model_class = related_instance_or_manager .__class__
2332 serializer = self .get_serializer (data = request .data , model_class = related_model_class )
2433 serializer .is_valid (raise_exception = True )
2534 setattr (parent_obj , kwargs ['related_field' ], serializer .validated_data )
2635 parent_obj .save ()
27- return Response (serializer .data )
36+ result_serializer = self ._instantiate_serializer (related_instance_or_manager )
37+ return Response (result_serializer .data )
2838
2939 def post (self , request , * args , ** kwargs ):
30- return Response ()
40+ related_instance_or_manager = self .get_related_instance ()
41+
42+ if isinstance (related_instance_or_manager , BaseManager ):
43+ related_model_class = related_instance_or_manager .model
44+ serializer = self .get_serializer (data = request .data , model_class = related_model_class , many = True )
45+ serializer .is_valid (raise_exception = True )
46+ if frozenset (serializer .validated_data ) <= frozenset (related_instance_or_manager .all ()):
47+ return Response (status = 204 )
48+ related_instance_or_manager .add (* serializer .validated_data )
49+ else :
50+ raise MethodNotAllowed ('POST' )
51+ result_serializer = self ._instantiate_serializer (related_instance_or_manager )
52+ return Response (result_serializer .data )
3153
3254 def delete (self , request , * args , ** kwargs ):
33- return Response ()
55+ related_instance_or_manager = self .get_related_instance ()
56+
57+ if isinstance (related_instance_or_manager , BaseManager ):
58+ related_model_class = related_instance_or_manager .model
59+ serializer = self .get_serializer (data = request .data , model_class = related_model_class , many = True )
60+ serializer .is_valid (raise_exception = True )
61+ if frozenset (serializer .validated_data ).isdisjoint (frozenset (related_instance_or_manager .all ())):
62+ return Response (status = 204 )
63+ try :
64+ related_instance_or_manager .remove (* serializer .validated_data )
65+ except AttributeError :
66+ raise Conflict (
67+ 'This object cannot be removed from this relationship without being added to another'
68+ )
69+ else :
70+ raise MethodNotAllowed ('DELETE' )
71+ result_serializer = self ._instantiate_serializer (related_instance_or_manager )
72+ return Response (result_serializer .data )
3473
3574 def get_related_instance (self ):
3675 try :
0 commit comments