Skip to content

Commit af1ac1d

Browse files
committed
fixed bug with 'field' filters propagating to child serializers
1 parent 00675cd commit af1ac1d

File tree

1 file changed

+46
-19
lines changed

1 file changed

+46
-19
lines changed

api_v2/serializers/abstracts.py

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,15 @@ def set_dynamic_params_for_children(self, dynamic_params):
3636
"""
3737
for param, fields in dynamic_params.items():
3838
child, child_dynamic_param = self.split_param(param)
39-
if child in set(self.fields.keys()):
40-
dynamic_params = self.get_or_create_dynamic_params(child)
41-
dynamic_params.update({child_dynamic_param: fields})
39+
if child in self.fields.keys():
40+
# Get dynamic parameters for child serializer and update
41+
child_dynamic_params = self.get_or_create_dynamic_params(child)
42+
child_dynamic_params.update({child_dynamic_param: fields})
43+
44+
# Overwrite existing params to remove 'fields' inherited from parent serializer
45+
self.fields[child]._context['dynamic_params'] = {
46+
**child_dynamic_params,
47+
}
4248

4349
@staticmethod
4450
def is_param_dynamic(p):
@@ -53,6 +59,41 @@ def get_dynamic_params(self):
5359
return self.parent._context.get("dynamic_params", {})
5460
return self._context.get("dynamic_params", {})
5561

62+
def handle_depth_serialization(self, instance, representation):
63+
"""
64+
Handles the serialization of fields based on the current depth
65+
compared to the maximum allowed depth. This function modifies
66+
the representation to include only URLs for nested serializers
67+
when the maximum depth is reached.
68+
"""
69+
max_depth = self._context.get("max_depth", 0)
70+
current_depth = self._context.get("current_depth", 0)
71+
72+
# if we reach the maximum depth, nested serializers return their pk
73+
if current_depth >= max_depth:
74+
for field_name, field in self.fields.items():
75+
if isinstance(field, serializers.HyperlinkedModelSerializer):
76+
nested_representation = representation.get(field_name)
77+
if nested_representation and "url" in nested_representation:
78+
representation[field_name] = nested_representation["url"]
79+
80+
# otherwise, pass depth to children serializers
81+
else:
82+
for field_name, field in self.fields.items():
83+
if isinstance(field, GameContentSerializer):
84+
nested_instance = getattr(instance, field_name)
85+
nested_serializer = field.__class__(nested_instance, context={
86+
**self._context,
87+
"current_depth": current_depth + 1,
88+
"max_depth": max_depth,
89+
})
90+
# Ensure dynamic params are specific to the child serializer
91+
child_dynamic_params = self.get_or_create_dynamic_params(field_name)
92+
nested_serializer._context['dynamic_params'] = child_dynamic_params
93+
representation[field_name] = nested_serializer.data
94+
95+
return representation
96+
5697
def __init__(self, *args, **kwargs):
5798
request = kwargs.get("context", {}).get("request")
5899
super().__init__(*args, **kwargs)
@@ -66,30 +107,16 @@ def to_representation(self, instance):
66107
max_depth = self._context.get("max_depth", 0)
67108
current_depth = self._context.get("current_depth", 0)
68109

69-
# Process dynamic parameters for filtering fields
70110
if dynamic_params := self.get_dynamic_params().copy():
71111
self.remove_unwanted_fields(dynamic_params)
72112
self.set_dynamic_params_for_children(dynamic_params)
73113

74-
# Collect only the fields that need to be included in the representation
75114
representation = super().to_representation(instance)
76115

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
116+
representation = self.handle_depth_serialization(instance, representation)
91117

92118
return representation
93119

120+
94121
class Meta:
95122
abstract = True

0 commit comments

Comments
 (0)