Skip to content

Commit 03dc92d

Browse files
committed
fixed N+1 error on v2/creatures endpoint
1 parent 8a3f15a commit 03dc92d

File tree

4 files changed

+36
-20
lines changed

4 files changed

+36
-20
lines changed
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Generated by Django 5.1.2 on 2025-03-26 10:46
2+
3+
import django.db.models.deletion
4+
from django.db import migrations, models
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('api_v2', '0026_delete_searchresult'),
11+
]
12+
13+
operations = [
14+
migrations.AlterField(
15+
model_name='creatureaction',
16+
name='parent',
17+
field=models.ForeignKey(help_text='The creature to which this action belongs.', on_delete=django.db.models.deletion.CASCADE, related_name='actions', to='api_v2.creature'),
18+
),
19+
migrations.AlterField(
20+
model_name='creatureactionattack',
21+
name='parent',
22+
field=models.ForeignKey(help_text='The creature action to which this attack belongs.', on_delete=django.db.models.deletion.CASCADE, related_name='attacks', to='api_v2.creatureaction'),
23+
),
24+
]

api_v2/models/creature.py

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ def get_initiative_bonus(self):
102102

103103
def as_text(self):
104104
text = self.name + '\n'
105-
for action in self.creatureaction_set.all():
105+
for action in self.actions.all():
106106
text+='\n' + action.as_text()
107107

108108
return text
@@ -113,12 +113,7 @@ def search_result_extra_fields(self):
113113
"type": self.type.name,
114114
"size": self.size.name,
115115
}
116-
117-
@property
118-
def creatureset(self):
119-
'''Helper method to rename and return creaturesets.'''
120-
return self.creaturesets.all()
121-
116+
122117
@property
123118
def challenge_rating_text(self):
124119
'''Challenge rating as text string representation of a fraction or integer. '''
@@ -171,19 +166,14 @@ def experience_points(self):
171166
except:
172167
return None
173168

174-
@property
175-
def actions(self):
176-
"""Returns the set of actions that are related to this creature."""
177-
return self.creatureaction_set
178-
179-
180169
class CreatureAction(HasName, HasDescription):
181170
"""Describes an action available to a creature."""
182171
key = key_field()
183172

184173
parent = models.ForeignKey(
185174
Creature,
186175
on_delete=models.CASCADE,
176+
related_name='actions',
187177
help_text='The creature to which this action belongs.'
188178
)
189179

@@ -232,16 +222,13 @@ def as_text(self):
232222

233223
return text
234224

235-
def attacks(self):
236-
return self.creatureactionattack_set
237-
238-
239225
class CreatureActionAttack(HasName):
240226
"""Describes an attack action used by a creature."""
241227
key = key_field()
242228

243229
parent = models.ForeignKey(
244230
CreatureAction,
231+
related_name="attacks",
245232
on_delete=models.CASCADE,
246233
help_text='The creature action to which this attack belongs.'
247234
)

api_v2/serializers/creature.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def get_distance_unit(self, CreatureActionAttack):
3232

3333
class CreatureActionSerializer(serializers.ModelSerializer):
3434
key = serializers.ReadOnlyField()
35-
attacks = CreatureActionAttackSerializer(many=True)
35+
attacks = CreatureActionAttackSerializer(many=True, read_only=True)
3636
class Meta:
3737
model = models.CreatureAction
3838
fields = '__all__'

api_v2/views/creature.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,20 +66,25 @@ class CreatureViewSet(EagerLoadingMixin, viewsets.ReadOnlyModelViewSet):
6666
serializer_class = serializers.CreatureSerializer
6767
filterset_class = CreatureFilterSet
6868

69+
select_related_fields = []
70+
6971
prefetch_related_fields = [
72+
'actions',
73+
'actions__attacks',
74+
'creaturesets',
7075
'condition_immunities',
71-
'creatureaction_set',
7276
'damage_immunities',
7377
'damage_resistances',
7478
'damage_vulnerabilities',
7579
'document',
76-
'document__gamesystem',
7780
'document__publisher',
81+
'document__gamesystem',
7882
'environments',
7983
'languages',
8084
'languages__document',
8185
'type',
8286
'size',
87+
'size__document',
8388
'traits',
8489
]
8590

0 commit comments

Comments
 (0)