在Django Rest Framework中,使用ModelSerializer选择相关的queryset。

9 浏览
0 Comments

在Django Rest Framework中,使用ModelSerializer选择相关的queryset。

我正在尝试在DRF序列化器中使用"select_related"查询集方法,但是这个例子仍然执行了很多SQL查询。如何从"select_related"方法中获取相关的对象"model_b"呢?

以下是用精炼的语言翻译的内容:

我正在尝试在DRF序列化器中使用"select_related"查询集方法,但是这个例子仍然执行了很多SQL查询。如何从"select_related"方法中获取相关的对象"model_b"呢?

class Model_A(models.Model):
    title = models.CharField(max_length=100)
    description = models.TextField()
    model_b = models.ForeignKey(Model_B, null=True, blank=True)
    
class Model_B(models.Model):
    title = models.CharField(max_length=100)
    
class Model_A_Serializer(serializers.ModelSerializer):
    model_b = Model_B_Serializer(source="model_b")
    
    class Meta:
        model = Model_A
        fields = ('title', 'model_b')
        
class Model_B_Serializer(serializers.ModelSerializer):
    class Meta:
        model = Model_B
    
class Model_A_View(viewsets.ModelViewSet):
    serializer_class = Model_A_Serializer
    queryset = Model_A.objects.select_related('model_b').all()

0
0 Comments

在Django Rest Framework中使用ModelSerializer时,遇到了一个问题:如何在查询中使用select_related queryset。

问题的原因是,使用select_related时,不会立即获取到关联模型的数据,而是在使用关联模型时才会执行额外的查询。这样会导致在使用ModelSerializer时,每个关联模型都会执行一次查询,导致性能下降。

解决这个问题的方法是使用prefetch_related。prefetch_related会一次性获取所有关联模型的数据,从而避免了多次查询的问题。在查询中使用prefetch_related的方法如下:

queryset = Model_A.objects.all().prefetch_related('model_b')

这样,在使用ModelSerializer时,就可以避免多次查询的性能问题了。

另外,如果想要将sql查询日志打印到控制台,可以参考这个答案:

import logging
l = logging.getLogger('django.db.backends')
l.setLevel(logging.DEBUG)
l.addHandler(logging.StreamHandler())

最后,需要注意的是,select_related和prefetch_related在处理ManyToMany关系时的行为是不同的。select_related会通过join将关联模型的数据包含在原始查询中,而prefetch_related会通过单独的查询并使用WHERE ... IN ()来获取关联模型的数据。

通过使用prefetch_related queryset可以解决在Django Rest Framework中使用ModelSerializer时的性能问题。

0