【发布时间】:2021-11-19 02:39:30
【问题描述】:
我的 Django 模型:
class Quest(models.Model):
name = models.CharField(max_length=255)
is_completed = models.BooleanField(default=False)
characters = models.ManyToManyField(Character, blank=True)
campaign = models.ForeignKey(Campaign, on_delete=models.CASCADE, editable=False)
DRF 序列化器:
class QuestSerializer(serializers.ModelSerializer):
characters = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
class Meta:
model = Quest
fields = "__all__"
我遇到的问题是,当我获取任务列表时,它会执行如下查询:
SELECT ("quests_quest_characters"."quest_id") AS
"_prefetch_related_val_quest_id", "characters_character"."id",
"characters_character"."legacy_id", "characters_character"."name",
"characters_character"."subtitle", "characters_character"."avatar",
"characters_character"."avatar_crop", "characters_character"."text",
"characters_character"."is_npc", "characters_character"."is_hidden",
"characters_character"."dm_notes",
"characters_character"."campaign_id",
"characters_character"."created_at",
"characters_character"."updated_at" FROM "characters_character" INNER
JOIN "quests_quest_characters" ON ("characters_character"."id" =
"quests_quest_characters"."character_id") WHERE
"quests_quest_characters"."quest_id" IN (1281, 1280, 1279, 1278, 1277,
1276, 1275, 1274, 1273, 1272, 1271, 1270, 1269, 1268, 1267, 1266,
1265, 1264, 1263, 1262, 1261, 1260, 1259, 1258, 1257, 1256, 1255,
1254)
这是一个包含很多字段的大查询,即使在 JSON 结果中只返回了一个字符 id 数组,那么它为什么要获取所有这些信息呢?它应该只是获取这个,我想:
SELECT "character_id" FROM "quests_quest_characters" WHERE "quest_id" IN (1281, 1280, 1279, 1278, 1277,
1276, 1275, 1274, 1273, 1272, 1271, 1270, 1269, 1268, 1267, 1266,
1265, 1264, 1263, 1262, 1261, 1260, 1259, 1258, 1257, 1256, 1255,
1254)
我的看法:
class QuestController(viewsets.ModelViewSet):
serializer_class = QuestSerializer
def get_queryset(self):
return Quest.objects.filter(campaign_id=self.kwargs["campaign_id"]).prefetch_related("characters")
def perform_create(self, serializer):
return serializer.save(campaign_id=self.kwargs["campaign_id"])
我正在使用prefetch_related("characters"),否则它会每个字符执行一个查询,如果您有很多包含大量字符的任务,这可能会导致视图执行数百个查询。
所以我的问题是:我可以使获取字符的查询更简单吗?毕竟我只返回一个字符ID数组,所以应该不需要获取整个字符,内部加入了 quests_quest_characters 表。
【问题讨论】:
标签: django django-models django-rest-framework django-queryset