我如何在rest框架中使用select_related

时间:2017-02-04 19:07:01

标签: django django-rest-framework

我是django的新手,我正在创建基本网站,用户可以发布一些消息并在该帖子中添加一些标签。我有3个模型人物,帖子和标签。使用rest框架我为帖子创建了API,它应该给我一些帖子列表,其中包含人名,帖子与帖子有关。对于少量的帖子,这工作正常,但对于大型帖子,回复时间太长。使用django-toolbar我能够找出太多的查询被触发,所以我在queryset中使用了prefetch_related和select_related。这里查询数量减少了一半,但仍然为每个记录执行外键关系船查询。下面是我的代码示例。

为了获得10条记录,它不会在标签模型上使用prefetch_related来触发34个查询。

在Tags上使用prefetch_related后,它是15个查询。现在对于个人帖子,它是对自我加入的人发起查询。如何减少这些查询次数?

models.py

class Tag(models.Model):
    name = models.CharField(max_length=200,unique=True)

    def __str__(self):
        return self.name

class Person(models.Model):
    name = models.CharField(max_length=200,unique=True)
    friends = models.ManyToManyField("self", blank=True)

    def __str__(self):
        return self.name

class Post(models.Model):
    person_id = models.ForeignKey(Person)
    text = models.TextField(blank=True,null=True)
    related_tags = models.ManyToManyField(Tag)

    def __str__(self):
        return self.text



serilizers.py

class PostSerializer(serializers.HyperlinkedModelSerializer):

    @staticmethod
    def setup_eager_loading(queryset):
        queryset = queryset.select_related("person_id").prefetch_related("related_tags")
        return queryset

    class Meta:
        model = Post
        fields = ('url', 'id', 'text','related_tags','person_id')
        # fields = '__all__'
        depth = 1
views.py
class PostViewSet(viewsets.ModelViewSet):
    queryset = PostSerializer.setup_eager_loading(Post.objects.all())
    serializer_class = PostSerializer

以下是各自出现的查询列表。

SELECT `myapp_post`.`id`, `myapp_post`.`person_id_id`, `myapp_post`.`text`, `myapp_person`.`id`, `myapp_person`.`name` 
FROM `myapp_post` INNER JOIN `myapp_person` ON (`myapp_post`.`person_id_id` = `myapp_person`.`id`)
LIMIT 10

发生 - 一次

SELECT (`myapp_post_related_tags`.`post_id`) AS `_prefetch_related_val_post_id`, `myapp_tag`.`id`, `myapp_tag`.`name`
FROM `myapp_tag` INNER JOIN `myapp_post_related_tags` ON (`myapp_tag`.`id` = `myapp_post_related_tags`.`tag_id`)
WHERE `myapp_post_related_tags`.`post_id` IN (11, 12, 13, 14, 15, 16, 17, 18, 19, 20)

发生 - 一次

SELECT `myapp_person`.`id`, `myapp_person`.`name`
FROM `myapp_person` INNER JOIN `myapp_person_related_persons` ON (`myapp_person`.`id` = `myapp_person_related_persons`.`to_person_id`)
WHERE `myapp_person_related_persons`.`from_person_id` = 704692

发生 - 10次记录10次

0 个答案:

没有答案