我是django rest框架的新手,我有一个项目,需要优化现有API端点的响应时间。使用django调试工具栏,找到了一些使用prefetch_related()减少SQL查询的方法。问题是,我发现序列化程序的设计是使用多个SerializerMethodField来获取其统计值,并且使用prefetch_related仅在all()上有效,但在第二个序列化程序方法字段上,仍然会为每个类循环查询filter()。您可能会看到下面的示例代码(这不是特定的代码,而是类似这样的代码)
serializer.py:
class ClassStatisticsSerializer(ModelBaseSerializer):
total_sessions = serializers.SerializerMethodField()
activity_count = serializers.SerializerMethodField()
def get_total_sessions(self, instance):
sessions = instance.classactivity_set.all()
date = self.context.get('date')
if date:
sessions = sessions.filter(date=date)
if len(sessions) == 0:
return None
return sessions.count()
def get_activity_count(self, instance):
activities = instance.classactivity_set.filter(is_present=False)
date = self.context.get('date')
if date:
activities = activities.filter(date=date)
if len(activities) == 0:
return None
return activities.count()
class Meta:
model = Class
fields = (
'id',
'batch',
'type,
'total_sessions'
'activity_count'
)
views.py:
class ClassStatisticsList(APIView):
def get(self, request, *args, **kwargs):
queryset = Class.objects.all().prefetch_related('classactivity_set')
serializer = ClassStatisticsSerializer()
return Response(serializer, status=status.HTTP_200_OK)
在这里,当我检查django debug工具栏上的SQL查询时,get_total_会话在SQL上被查询了一次,但get_activity_计数没有,因为这是SQL上的另一个查询请求,并且每个类循环都被查询。现在,制作一个新模型是不可能的,所以我一直在研究如何正确地预取第二个查询请求。希望您能提出可能的解决方法。提前谢谢各位
您可以annotate使用queryset计算对象的计数,然后通过序列化程序类初始化传递它。像这样:
然后您需要从序列化程序中删除
SerializerMethodField
,一个简单的整数字段应该足以从queryset中获取数据,而无需额外的db命中:相关问题 更多 >
编程相关推荐