Skip to content

Commit 1eb97a2

Browse files
authored
Merge pull request #18 from MaxDude132/feature/allow-force-prefetch
allow-force-prefetch - Add parameter to allow forcing the prefetching…
2 parents 40d86f7 + ef0e344 commit 1eb97a2

File tree

4 files changed

+297
-218
lines changed

4 files changed

+297
-218
lines changed

serializer_prefetch/base.py

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ def get_additional_serializers_data(self, serializer):
3636

3737
return getattr(serializer, "additional_serializers", [])
3838

39+
def get_force_prefetch_data(self, serializer):
40+
if hasattr(serializer, "get_force_prefetch"):
41+
return serializer.get_force_prefetch()
42+
43+
return getattr(serializer, "force_prefetch", [])
44+
3945
def other_prefetching(self):
4046
"""
4147
Override this method to add additional prefetching that
@@ -83,8 +89,9 @@ def get_prefetch(
8389
if hasattr(serializer, "child"):
8490
serializer = serializer.child
8591

92+
force_prefetch = self.get_force_prefetch_data(serializer)
8693
select_items, prefetch_items = self._get_custom_relations(
87-
serializer, current_relation
94+
serializer, current_relation, force_prefetch=force_prefetch
8895
)
8996
self._extend_relation_items(
9097
select_items,
@@ -127,10 +134,17 @@ def _extend_relation_items(
127134

128135
return select_items, prefetch_items
129136

130-
def _get_custom_relations(self, serializer, current_relation):
131-
select_related_attr = self.get_select_related_data(serializer)
137+
def _get_custom_relations(self, serializer, current_relation, *, force_prefetch=()):
138+
select_related_attr = []
139+
temp_select_related_attr = self.get_select_related_data(serializer)
132140
prefetch_related_attr = self.get_prefetch_related_data(serializer)
133141

142+
for select in temp_select_related_attr:
143+
if select in force_prefetch:
144+
prefetch_related_attr.append(select)
145+
else:
146+
select_related_attr.append(select)
147+
134148
custom_select_related = (
135149
self._get_custom_related(select_related_attr, current_relation) or []
136150
)
@@ -202,6 +216,7 @@ def _get_serializer_field_relations(
202216
return select_items, prefetch_items
203217

204218
info = model_meta.get_field_info(model)
219+
force_prefetch = self.get_force_prefetch_data(serializer)
205220

206221
for field in serializer.fields.values():
207222
if field.write_only:
@@ -223,7 +238,11 @@ def _get_serializer_field_relations(
223238
if relation.to_many:
224239
future_should_prefetch = True
225240

226-
append_to = prefetch_items if future_should_prefetch else select_items
241+
append_to = (
242+
prefetch_items
243+
if future_should_prefetch or source in force_prefetch
244+
else select_items
245+
)
227246

228247
if should_prefetch:
229248
source = Prefetch(source)
@@ -331,19 +350,10 @@ def to_representation(self, instance, *args, **kwargs):
331350
child = self.child
332351
select_items, prefetch_items = self.get_prefetch(child)
333352

334-
prefetch_has_prefetch_objects = any(
335-
isinstance(p, Prefetch) and p.prefetch_to != p.prefetch_through
336-
for p in prefetch_items
337-
)
338-
339353
if isinstance(instance, QuerySet):
340-
instance = instance.prefetch_related(
341-
*self.get_ordered_prefetches(prefetch_items)
342-
)
343-
if not prefetch_has_prefetch_objects:
354+
if select_items:
344355
instance = instance.select_related(*select_items)
345-
else:
346-
instance = instance.prefetch_related(*select_items)
356+
instance = instance.prefetch_related(*prefetch_items)
347357
instance = self.queryset_after_prefetch(instance)
348358

349359
else:
@@ -385,9 +395,7 @@ def to_representation(self, instance, *args, **kwargs):
385395
):
386396
select_items, prefetch_items = self.get_prefetch(self)
387397

388-
for related_lookup in (
389-
list(self.get_ordered_prefetches(prefetch_items)) + select_items
390-
):
398+
for related_lookup in select_items + prefetch_items:
391399
try:
392400
prefetch_related_objects([instance], related_lookup)
393401
except AttributeError as exc:

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from setuptools import setup, find_packages
33

44

5-
VERSION = "1.1.2"
5+
VERSION = "1.1.3"
66
DESCRIPTION = "An automatic prefetcher for django-rest-framework."
77
this_directory = Path(__file__).parent
88
LONG_DESCRIPTION = (this_directory / "README.md").read_text()

0 commit comments

Comments
 (0)