Skip to content

Commit 7d445b0

Browse files
committed
refactored views to use new EagerLoadingMixin
1 parent a36918d commit 7d445b0

File tree

14 files changed

+99
-237
lines changed

14 files changed

+99
-237
lines changed

api_v2/views/ability.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from api_v2 import models
66
from api_v2 import serializers
7-
7+
from .mixins import EagerLoadingMixin
88

99
class AbilityFilterSet(FilterSet):
1010
class Meta:
@@ -37,7 +37,7 @@ class Meta:
3737
}
3838

3939

40-
class SkillViewSet(viewsets.ReadOnlyModelViewSet):
40+
class SkillViewSet(EagerLoadingMixin, viewsets.ReadOnlyModelViewSet):
4141
"""
4242
list: API endpoint for returning a list of skills.
4343
retrieve: API endpoint for returning a particular skill.

api_v2/views/alignment.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from api_v2 import models
66
from api_v2 import serializers
77

8+
from .mixins import EagerLoadingMixin
89

910
class AlignmentFilterSet(FilterSet):
1011
class Meta:
@@ -16,11 +17,13 @@ class Meta:
1617
'document__gamesystem__key': ['in','iexact','exact'],
1718
}
1819

19-
class AlignmentViewSet(viewsets.ReadOnlyModelViewSet):
20+
class AlignmentViewSet(EagerLoadingMixin, viewsets.ReadOnlyModelViewSet):
2021
"""
2122
list: API endpoint for returning a list of alignments.
2223
retrieve: API endpoint for returning a particular alignment.
2324
"""
2425
queryset = models.Alignment.objects.all().order_by('pk')
2526
serializer_class = serializers.AlignmentSerializer
26-
filterset_class = AlignmentFilterSet
27+
filterset_class = AlignmentFilterSet
28+
29+
prefetch_related_fields = ['document']

api_v2/views/background.py

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from api_v2 import models
77
from api_v2 import serializers
8-
8+
from .mixins import EagerLoadingMixin
99

1010
class BackgroundFilterSet(FilterSet):
1111
class Meta:
@@ -18,7 +18,7 @@ class Meta:
1818
}
1919

2020

21-
class BackgroundViewSet(viewsets.ReadOnlyModelViewSet):
21+
class BackgroundViewSet(EagerLoadingMixin, viewsets.ReadOnlyModelViewSet):
2222
"""
2323
list: API endpoint for returning a list of backgrounds.
2424
retrieve: API endpoint for returning a particular background.
@@ -27,15 +27,4 @@ class BackgroundViewSet(viewsets.ReadOnlyModelViewSet):
2727
serializer_class = serializers.BackgroundSerializer
2828
filterset_class = BackgroundFilterSet
2929

30-
def get_queryset(self):
31-
depth = int(self.request.query_params.get('depth', 0)) # get 'depth' from query params
32-
return BackgroundViewSet.setup_eager_loading(super().get_queryset(), self.action, depth)
33-
34-
@staticmethod
35-
def setup_eager_loading(queryset, action, depth):
36-
# Apply select_related and prefetch_related based on action and depth
37-
if action == 'list':
38-
selects = []
39-
prefetches = ['benefits'] # Many-to-many/rvrs relationships to prefetch
40-
queryset = queryset.select_related(*selects).prefetch_related(*prefetches)
41-
return queryset
30+
prefetch_related_fields = ['benefits']

api_v2/views/characterclass.py

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from django_filters import FilterSet
55
from django_filters import BooleanFilter
6+
from .mixins import EagerLoadingMixin
67

78
from api_v2 import models
89
from api_v2 import serializers
@@ -22,7 +23,7 @@ class Meta:
2223
}
2324

2425

25-
class CharacterClassViewSet(viewsets.ReadOnlyModelViewSet):
26+
class CharacterClassViewSet(EagerLoadingMixin, viewsets.ReadOnlyModelViewSet):
2627
"""
2728
list: API endpoint for returning a list of classes.
2829
retrieve: API endpoint for returning a particular class.
@@ -31,18 +32,5 @@ class CharacterClassViewSet(viewsets.ReadOnlyModelViewSet):
3132
serializer_class = serializers.CharacterClassSerializer
3233
filterset_class = CharacterClassFilterSet
3334

34-
"""
35-
Set up selects and prefetching nested joins to mitigate N+1 problems
36-
"""
37-
def get_queryset(self):
38-
depth = int(self.request.query_params.get('depth', 0)) # get 'depth' from query params
39-
return CharacterClassViewSet.setup_eager_loading(super().get_queryset(), self.action, depth)
40-
41-
@staticmethod
42-
def setup_eager_loading(queryset, action, depth):
43-
# Apply select_related and prefetch_related based on action and depth
44-
if action == 'list':
45-
selects = ['document']
46-
prefetches = [] # Many-to-many/rvrs relationships to prefetch
47-
queryset = queryset.select_related(*selects).prefetch_related(*prefetches)
48-
return queryset
35+
select_related_fields = []
36+
prefetch_related_fields = ['document', 'saving_throws', 'features', 'subclass_of']

api_v2/views/condition.py

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from api_v2 import models
66
from api_v2 import serializers
7-
7+
from .mixins import EagerLoadingMixin
88

99
class ConditionFilterSet(FilterSet):
1010
class Meta:
@@ -17,7 +17,7 @@ class Meta:
1717
}
1818

1919

20-
class ConditionViewSet(viewsets.ReadOnlyModelViewSet):
20+
class ConditionViewSet(EagerLoadingMixin, viewsets.ReadOnlyModelViewSet):
2121
"""
2222
list: API endpoint for returning a list of conditions.
2323
retrieve: API endpoint for returning a particular condition.
@@ -26,18 +26,5 @@ class ConditionViewSet(viewsets.ReadOnlyModelViewSet):
2626
serializer_class = serializers.ConditionSerializer
2727
filterset_class = ConditionFilterSet
2828

29-
"""
30-
Set up selects and prefetching nested joins to mitigate N+1 problems
31-
"""
32-
def get_queryset(self):
33-
depth = int(self.request.query_params.get('depth', 0)) # get 'depth' from query params
34-
return ConditionViewSet.setup_eager_loading(super().get_queryset(), self.action, depth)
35-
36-
@staticmethod
37-
def setup_eager_loading(queryset, action, depth):
38-
# Apply select_related and prefetch_related based on action and depth
39-
if action == 'list':
40-
selects = ['document', 'document__gamesystem', 'document__publisher']
41-
prefetches = [] # Many-to-many/rvrs relationships to prefetch
42-
queryset = queryset.select_related(*selects).prefetch_related(*prefetches)
43-
return queryset
29+
select_related_fields = []
30+
prefetch_related_fields = ['document__gamesystem']

api_v2/views/creature.py

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from api_v2 import models
66
from api_v2 import serializers
77

8+
from .mixins import EagerLoadingMixin
89

910
class CreatureFilterSet(FilterSet):
1011
'''This is the filterset class for creatures.'''
@@ -56,7 +57,7 @@ class Meta:
5657
}
5758

5859

59-
class CreatureViewSet(viewsets.ReadOnlyModelViewSet):
60+
class CreatureViewSet(EagerLoadingMixin, viewsets.ReadOnlyModelViewSet):
6061
"""
6162
list: API endpoint for returning a list of creatures.
6263
retrieve: API endpoint for returning a particular creature.
@@ -65,38 +66,22 @@ class CreatureViewSet(viewsets.ReadOnlyModelViewSet):
6566
serializer_class = serializers.CreatureSerializer
6667
filterset_class = CreatureFilterSet
6768

68-
def get_queryset(self):
69-
depth = int(self.request.query_params.get('depth', 0)) # get 'depth' from query params
70-
return CreatureViewSet.setup_eager_loading(super().get_queryset(), self.action, depth)
71-
72-
@staticmethod
73-
def setup_eager_loading(queryset, action, depth):
74-
# Apply select_related and prefetch_related based on action and depth
75-
if action == 'list':
76-
selects = [
77-
'document',
78-
'document__gamesystem',
79-
'document',
80-
'document__publisher',
81-
'size',
82-
'type',
83-
]
84-
85-
# Many-to-many and reverse relationships for prefetching
86-
prefetches = [
87-
'creatureaction_set',
88-
'condition_immunities',
89-
'damage_immunities',
90-
'damage_resistances',
91-
'damage_vulnerabilities',
92-
'environments',
93-
'languages',
94-
'languages__document',
95-
'traits'
96-
]
97-
98-
queryset = queryset.select_related(*selects).prefetch_related(*prefetches)
99-
return queryset
69+
prefetch_related_fields = [
70+
'condition_immunities',
71+
'creatureaction_set',
72+
'damage_immunities',
73+
'damage_resistances',
74+
'damage_vulnerabilities',
75+
'document',
76+
'document__gamesystem',
77+
'document__publisher',
78+
'environments',
79+
'languages',
80+
'languages__document',
81+
'type',
82+
'size',
83+
'traits',
84+
]
10085

10186

10287
class CreatureTypeFilterSet(FilterSet):

api_v2/views/document.py

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
from rest_framework import viewsets
33
from django_filters import FilterSet, CharFilter
44
from django.db.models import JSONField
5-
5+
from .mixins import EagerLoadingMixin
66
from api_v2 import models
77
from api_v2 import serializers
88

@@ -30,7 +30,7 @@ class Meta:
3030
}
3131
}
3232

33-
class DocumentViewSet(viewsets.ReadOnlyModelViewSet):
33+
class DocumentViewSet(EagerLoadingMixin, viewsets.ReadOnlyModelViewSet):
3434
"""
3535
list: API endpoint for returning a list of documents.
3636
retrieve: API endpoint for returning a particular document.
@@ -39,18 +39,9 @@ class DocumentViewSet(viewsets.ReadOnlyModelViewSet):
3939
serializer_class = serializers.DocumentSerializer
4040
filterset_class = DocumentFilterSet
4141

42-
def get_queryset(self):
43-
depth = int(self.request.query_params.get('depth', 0)) # get 'depth' from query params
44-
return DocumentViewSet.setup_eager_loading(super().get_queryset(), self.action, depth)
42+
select_related_fields = []
43+
prefetch_related_fields = ['licenses', 'gamesystem', 'publisher']
4544

46-
@staticmethod
47-
def setup_eager_loading(queryset, action, depth):
48-
# Apply select_related and prefetch_related based on action and depth
49-
if action == 'list':
50-
selects = ['gamesystem', 'publisher'] # follows foreign-key relationships
51-
prefetches = ['licenses'] # Many-to-many/reverse relationships for prefetching
52-
queryset = queryset.select_related(*selects).prefetch_related(*prefetches)
53-
return queryset
5445

5546
class PublisherViewSet(viewsets.ReadOnlyModelViewSet):
5647
"""

api_v2/views/feat.py

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
from rest_framework import viewsets
2-
32
from django_filters import FilterSet
43

54
from api_v2 import models
65
from api_v2 import serializers
7-
6+
from .mixins import EagerLoadingMixin
87

98
class FeatFilterSet(FilterSet):
109
class Meta:
@@ -17,7 +16,7 @@ class Meta:
1716
}
1817

1918

20-
class FeatViewSet(viewsets.ReadOnlyModelViewSet):
19+
class FeatViewSet(EagerLoadingMixin, viewsets.ReadOnlyModelViewSet):
2120
"""
2221
list: API endpoint for returning a list of feats.
2322
retrieve: API endpoint for returning a particular feat.
@@ -26,19 +25,6 @@ class FeatViewSet(viewsets.ReadOnlyModelViewSet):
2625
serializer_class = serializers.FeatSerializer
2726
filterset_class = FeatFilterSet
2827

29-
"""
30-
Set up selects and prefetching nested joins to mitigate N+1 problems
31-
"""
32-
def get_queryset(self):
33-
depth = int(self.request.query_params.get('depth', 0)) # get 'depth' from query param
34-
return FeatViewSet.setup_eager_loading(super().get_queryset(), self.action, depth)
35-
36-
@staticmethod
37-
def setup_eager_loading(queryset, action, depth):
38-
# Apply select_related and prefetch_related based on action and depth
39-
if action == 'list':
40-
selects = ['document', 'document__gamesystem', 'document__publisher']
41-
prefetches = ['benefits'] # Many-to-many/rvrs relationships to prefetch
42-
queryset = queryset.select_related(*selects).prefetch_related(*prefetches)
43-
return queryset
28+
select_related_fields = []
29+
prefetch_related_fields = ['benefits', 'document']
4430

api_v2/views/item.py

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
from django_filters import FilterSet
44
from django_filters import BooleanFilter
55

6-
76
from api_v2 import models
87
from api_v2 import serializers
8+
from .mixins import EagerLoadingMixin
99

1010
class ItemFilterSet(FilterSet):
1111
is_magic_item = BooleanFilter(field_name='rarity', lookup_expr='isnull', exclude=True)
@@ -26,7 +26,7 @@ class Meta:
2626
}
2727

2828

29-
class ItemViewSet(viewsets.ReadOnlyModelViewSet):
29+
class ItemViewSet(EagerLoadingMixin, viewsets.ReadOnlyModelViewSet):
3030
"""
3131
list: API endpoint for returning a list of items.
3232
@@ -36,27 +36,16 @@ class ItemViewSet(viewsets.ReadOnlyModelViewSet):
3636
serializer_class = serializers.ItemSerializer
3737
filterset_class = ItemFilterSet
3838

39-
def get_queryset(self):
40-
depth = int(self.request.query_params.get('depth', 0)) # get 'depth' from query param
41-
return ItemViewSet.setup_eager_loading(super().get_queryset(), self.action, depth)
42-
43-
# Eagerly load nested resources to address N+1 problems
44-
@staticmethod
45-
def setup_eager_loading(queryset, action, depth):
46-
if action == 'list':
47-
selects = ['armor', 'weapon']
48-
# Prefetch many-to-many and reverse ForeignKey relations
49-
prefetches = [
50-
'category',
51-
'document',
52-
'document__publisher',
53-
'damage_immunities',
54-
'damage_resistances',
55-
'damage_vulnerabilities',
56-
'rarity'
57-
]
58-
queryset = queryset.select_related(*selects).prefetch_related(*prefetches)
59-
return queryset
39+
select_related_fields = ['armor', 'weapon']
40+
prefetch_related_fields = [
41+
'armor',
42+
'category',
43+
'damage_immunities',
44+
'damage_resistances',
45+
'damage_vulnerabilities',
46+
'document',
47+
'rarity',
48+
]
6049

6150
class ItemRarityViewSet(viewsets.ReadOnlyModelViewSet):
6251
"""

0 commit comments

Comments
 (0)