Django - 序列化器中的源代码导致过多的数据库调用

时间:2014-11-06 16:08:04

标签: python django django-rest-framework

我正在尝试在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次!

还有其他替代方法吗?

提前致谢。

2 个答案:

答案 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 并不总能保证优化的数据库命中率,人们必须付出一些努力以尽量减少命中率。我们可以考虑在某些情况下,我们可以决定哪种选项最适合我们的情况:

  • ModelSerializer
  • ReadOnlyModelSerializer
  • 序列化器
  • ReadOnlySerializer

这里是对上述用例的一个很好的描述:

https://hakibenita.com/django-rest-framework-slow