![](/img/trans.png)
[英]django-rest-framework add SerializerMethodField to Serializer dynamically
[英]How to optimize django-rest-framework serializers with multiple queryset at SerializerMethodField()
我是 django-rest-framework 的新手,我有一个项目,我必须优化现有 API 端点的响应时间。 使用 django-debug-toolbar,找到了一些使用 prefetch_related() 来减少 SQL 查询的方法。 问题是我发现序列化器的设计是有多个 SerializerMethodField 来获取它的统计值,并且使用 prefetch_related 仅适用于 all() 但在第二个序列化器方法字段上仍然会为每个 Class 循环查询 filter() 。 您可能会在下面看到示例代码(这不是特定代码,而是类似的代码)。
序列化程序.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'
)
视图.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)
In here, when I check the SQL queries on the django debug toolbar, get_total_sessions was being queried once on the SQL but get_activity_count was not since this is another query request on the SQL and being queried for every Class loop. 目前,制作一个新的 model 是不可能的,所以我被困在如何正确预取第二个查询请求上。 希望您能提出解决此问题的可能方法。 提前谢谢你们。
您可以使用查询集注释对象的计数,然后将其传递给序列化程序 class 初始化。 像这样:
from django.db.models import Count, Q
condition = {}
if date:
condition = {'date':date}
queryset = Class.objects.all().annotate(
total_sessions=Count(
'classactivity',
filter=Q(**condition),
distinct=True
),
activity_count=Count(
'classactivity',
filter=Q(**condition)&Q(classactivity__is_present=False),
distinct=True
)
)
然后你需要从你的序列化程序中删除SerializerMethodField
s,一个简单的 IntegerField 应该足以从查询集中获取数据而无需额外的数据库命中:
class ClassStatisticsSerializer(ModelBaseSerializer):
total_sessions = serializers.IntegerField()
activity_count = serializers.IntegerField()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.