33from rest_framework .fields import MISSING_ERROR_MESSAGE
44from rest_framework .relations import *
55from django .utils .translation import ugettext_lazy as _
6+ from django .db .models .query import QuerySet
67
78from rest_framework_json_api .exceptions import Conflict
89from rest_framework_json_api .utils import Hyperlink , \
910 get_resource_type_from_queryset , get_resource_type_from_instance , \
1011 get_included_serializers , get_resource_type_from_serializer
1112
12- import pdb
13-
14- JSONAPI_MANY_RELATION_KWARGS = ('model' , ) + MANY_RELATION_KWARGS
15-
16- class ManyResourceRelatedField (ManyRelatedField ):
17- """
18- Allows us to use serializer method RelatedFields
19- with return querysets
20- """
21- def __init__ (self , child_relation = None , * args , ** kwargs ):
22- model = kwargs .pop ('model' , None )
23- if model :
24- self .model = model
25- super (ManyResourceRelatedField , self ).__init__ (child_relation , * args , ** kwargs )
26-
27- def get_attribute (self , instance ):
28- if self .source and hasattr (self .parent , self .source ):
29- serializer_method = getattr (self .parent , self .source )
30- if hasattr (serializer_method , '__call__' ):
31- return serializer_method (instance )
32- return super (ManyResourceRelatedField , self ).get_attribute (instance )
33-
3413
3514class ResourceRelatedField (PrimaryKeyRelatedField ):
3615 self_link_view_name = None
@@ -47,21 +26,6 @@ class ResourceRelatedField(PrimaryKeyRelatedField):
4726 'no_match' : _ ('Invalid hyperlink - No URL match.' ),
4827 }
4928
50- def __new__ (cls , * args , ** kwargs ):
51- # We override this because getting
52- # serializer methods fails when many is true
53- if kwargs .pop ('many' , False ):
54- return cls .many_init (* args , ** kwargs )
55- return super (ResourceRelatedField , cls ).__new__ (cls , * args , ** kwargs )
56-
57- @classmethod
58- def many_init (cls , * args , ** kwargs ):
59- list_kwargs = {'child_relation' : cls (* args , ** kwargs )}
60- for key in kwargs .keys ():
61- if key in JSONAPI_MANY_RELATION_KWARGS :
62- list_kwargs [key ] = kwargs [key ]
63- return ManyResourceRelatedField (** list_kwargs )
64-
6529 def __init__ (self , self_link_view_name = None , related_link_view_name = None , ** kwargs ):
6630 if self_link_view_name is not None :
6731 self .self_link_view_name = self_link_view_name
@@ -205,11 +169,50 @@ def choices(self):
205169 ])
206170
207171
172+
208173class SerializerMethodResourceRelatedField (ResourceRelatedField ):
174+ """
175+ Allows us to use serializer method RelatedFields
176+ with return querysets
177+ """
178+ def __new__ (cls , * args , ** kwargs ):
179+ """
180+ We override this because getting serializer methods
181+ fails at the base class when many=True
182+ """
183+ if kwargs .pop ('many' , False ):
184+ return cls .many_init (* args , ** kwargs )
185+ return super (ResourceRelatedField , cls ).__new__ (cls , * args , ** kwargs )
186+
187+ def __init__ (self , child_relation = None , * args , ** kwargs ):
188+ # DRF 3.1 doesn't expect the `many` kwarg
189+ kwargs .pop ('many' , None )
190+ model = kwargs .pop ('model' , None )
191+ if model :
192+ self .model = model
193+ super (SerializerMethodResourceRelatedField , self ).__init__ (child_relation , * args , ** kwargs )
194+
195+ @classmethod
196+ def many_init (cls , * args , ** kwargs ):
197+ list_kwargs = {'child_relation' : cls (* args , ** kwargs )}
198+ for key in kwargs .keys ():
199+ if key in ('model' ,) + MANY_RELATION_KWARGS :
200+ list_kwargs [key ] = kwargs [key ]
201+ return SerializerMethodResourceRelatedField (** list_kwargs )
202+
209203 def get_attribute (self , instance ):
210204 # check for a source fn defined on the serializer instead of the model
211205 if self .source and hasattr (self .parent , self .source ):
212206 serializer_method = getattr (self .parent , self .source )
213207 if hasattr (serializer_method , '__call__' ):
214208 return serializer_method (instance )
215- return super (ResourceRelatedField , self ).get_attribute (instance )
209+ return super (SerializerMethodResourceRelatedField , self ).get_attribute (instance )
210+
211+ def to_representation (self , value ):
212+ if isinstance (value , QuerySet ):
213+ base = super (SerializerMethodResourceRelatedField , self )
214+ return [base .to_representation (x ) for x in value ]
215+ return super (SerializerMethodResourceRelatedField , self ).to_representation (value )
216+
217+ def get_links (self , obj = None , lookup_field = 'pk' ):
218+ return OrderedDict ()
0 commit comments