我正在尝试在Django中创建一个歌曲 - 艺术家 - 专辑关系。我有以下型号:
class Artist(models.Model):
gid = models.CharField(max_length=63, blank=True)
name = models.CharField(max_length=255, blank=True)
begin_life = models.CharField(max_length=31, blank=True)
end_life = models.CharField(max_length=31, blank=True)
type = models.CharField(max_length=1, blank=True)
gender = models.CharField(max_length=1, blank=True)
class Song(models.Model):
gid = models.CharField(max_length=63, blank=True)
title = models.CharField(max_length=255, blank=True)
artist = models.ForeignKey('Artist', related_name='songs_artist')
album = models.ForeignKey('Album', related_name='songs_album')
length = models.IntegerField(default=0)
我创建了ArtistSerializer,以便在获取任何特定艺术家的信息后,我可以检索艺术家的所有歌曲。这是我创建的序列化器:
class ArtistSerializer(serializers.ModelSerializer):
songs_artist = SongSerializer(source='songs_artist')
class Meta:
model = Artist
fields = ('name', 'type', 'gender', 'begin_life', 'end_life', 'songs_artist')
class SongSerializer(serializers.ModelSerializer):
artist = SongArtistSerializer()
album = SongAlbumSerializer()
class Meta:
model = Song
fields = ('id', 'title', 'artist', 'album', 'length')
class SongArtistSerializer(serializers.ModelSerializer):
class Meta:
model = Artist
fields = ('id', 'name')
对我艺术家的GET方法的快速描述揭示了一些令人不安的事实。以下是按时间和呼叫次数排序的分析结果:http://pastebin.com/bwcKsn2i。
但是,当我从序列化程序中删除songs_artist
字段时,以下是分析器的输出:http://pastebin.com/0s5k4w7i。
如果我读得正确,当我使用source
时,数据库会被点击1240次!
还有其他替代方法吗?
提前致谢。
答案 0 :(得分:3)
Django REST Framework不会为您优化您的查询,由您决定如何最好地删除任何N + 1查询。您应该遵循the Django documentation中涵盖的准则来处理性能问题。
对于ForeignKey关系,您应该在查询中使用select_related
,这将预取原始查询中的对象。
对于ManyToMany和GenericForeignKey关系,您应该使用prefetch_related
。我已经在another Stack Overflow answer中写了很多相关内容,但要点是你使用它与select_related
类似。
您应该在视图上覆盖get_queryset
中的查询以获得最佳结果,因为您不必担心Django REST Framework在用作类的属性时会错误地克隆查询集。
答案 1 :(得分:0)
序列化数据使用 DRF 并不总能保证优化的数据库命中率,人们必须付出一些努力以尽量减少命中率。我们可以考虑在某些情况下,我们可以决定哪种选项最适合我们的情况:
这里是对上述用例的一个很好的描述: