33
44from api_v2 import models
55
6-
76class GameContentSerializer (serializers .HyperlinkedModelSerializer ):
87
98 def remove_unwanted_fields (self , dynamic_params ):
109 """
11- Takes the value of the 'fields', a string of comma-seperated values,
10+ Takes the value of the 'fields', a string of comma-separated values,
1211 and removes all other fields from the serializer
1312 """
1413 if fields_to_keep := dynamic_params .pop ("fields" , None ):
@@ -28,24 +27,12 @@ def get_or_create_dynamic_params(self, child):
2827
2928 @staticmethod
3029 def split_param (dynamic_param ):
31- """
32- Splits a dynamic parameter into a key value pair. The key is used to
33- index into the serializers context to pass nested parameters
34-
35- document__fields=name -> ['document', 'fields=name']
36- document__licenses__fields=name -> ['document', 'licenses__fields=name']
37-
38- '__'s after the first are preserved so that the dynamic parameter can
39- be passed recursively down to more deeply-nested serializers
40- """
4130 crumbs = dynamic_param .split ("__" )
4231 return crumbs [0 ], "__" .join (crumbs [1 :]) if len (crumbs ) > 1 else None
4332
4433 def set_dynamic_params_for_children (self , dynamic_params ):
4534 """
46- Passes nested dynamic params to child serializer. ie.
47- "document__fields=name" would pass the query param "fields=name" to the
48- nested Document Serializer via the 'context' prop
35+ Passes nested dynamic params to child serializer.
4936 """
5037 for param , fields in dynamic_params .items ():
5138 child , child_dynamic_param = self .split_param (param )
@@ -55,68 +42,54 @@ def set_dynamic_params_for_children(self, dynamic_params):
5542
5643 @staticmethod
5744 def is_param_dynamic (p ):
58- """
59- Only the 'fields' query param supported, so we test for that
60- """
6145 return p .endswith ("fields" )
6246
6347 def get_dynamic_params_for_root (self , request ):
64- """
65- Checks query params in request and returns dynamic parameters
66- """
6748 query_params = request .query_params .items ()
6849 return {k : v for k , v in query_params if self .is_param_dynamic (k )}
6950
7051 def get_dynamic_params (self ):
71- """
72- When dynamic params get passed down in set_context_for_children
73- If the child is a subclass of ListSerializer (has many=True)
74- The context must be fetched from ListSerializer Class
75- """
7652 if isinstance (self .parent , serializers .ListSerializer ):
7753 return self .parent ._context .get ("dynamic_params" , {})
7854 return self ._context .get ("dynamic_params" , {})
7955
80- def set_depth (self , depth ):
81- """
82- Add appropriate 'depth' param to self.Meta based on 'depth' query param
83- """
84- if not depth :
85- self .Meta .depth = 0
86- return
87- try :
88- depth = int (depth )
89- if depth > 0 and depth < 3 :
90- # This value going above 1 could cause performance issues.
91- # Limited to 1 and 2 for now.
92- self .Meta .depth = depth
93- # Depth does not reset by default on subsequent requests with malformed urls.
94- else :
95- self .Meta .depth = 0
96- except ValueError :
97- pass # it was not castable to an int.
98-
99-
10056 def __init__ (self , * args , ** kwargs ):
10157 request = kwargs .get ("context" , {}).get ("request" )
10258 super ().__init__ (* args , ** kwargs )
10359
104-
105- # "request" doesn't exist on the child serializers, or when generating OAS spec
106- # So this if only evaluates as true on the root serializer
107-
108- is_root = bool (request )
109- if is_root :
110- self .set_depth (request .query_params .get ('depth' ))
60+ if request :
61+ self ._context ["max_depth" ] = int (request .query_params .get ("depth" , 0 ))
11162 dynamic_params = self .get_dynamic_params_for_root (request )
11263 self ._context .update ({"dynamic_params" : dynamic_params })
113-
114- def to_representation (self , * args , ** kwargs ):
64+
65+ def to_representation (self , instance ):
66+ max_depth = self ._context .get ("max_depth" , 0 )
67+ current_depth = self ._context .get ("current_depth" , 0 )
68+
69+ # Process dynamic parameters for filtering fields
11570 if dynamic_params := self .get_dynamic_params ().copy ():
11671 self .remove_unwanted_fields (dynamic_params )
11772 self .set_dynamic_params_for_children (dynamic_params )
11873
119- return super ().to_representation (* args , ** kwargs )
74+ # Collect only the fields that need to be included in the representation
75+ representation = super ().to_representation (instance )
76+
77+ if current_depth >= max_depth :
78+ # Remove fields that are HyperlinkedModelSerializers (nested fields)
79+ for field_name , field in self .fields .items ():
80+ if isinstance (field , serializers .HyperlinkedModelSerializer ):
81+ # Check if the nested field has a 'url' attribute in the representation
82+ nested_representation = representation .get (field_name )
83+ if nested_representation and "url" in nested_representation :
84+ # Replace the entire nested structure with the URL field
85+ representation [field_name ] = nested_representation ["url" ]
86+ else :
87+ # Update depth level in children
88+ for field_name , field in self .fields .items ():
89+ if isinstance (field , GameContentSerializer ):
90+ field ._context ["current_depth" ] = current_depth + 1
91+
92+ return representation
12093
12194 class Meta :
12295 abstract = True
0 commit comments