简体   繁体   English

如何在 SerializerMethodField() 使用多个查询集优化 django-rest-framework 序列化程序

[英]How to optimize django-rest-framework serializers with multiple queryset at SerializerMethodField()

I am new to django-rest-framework, and I have a project where I have to optimize the response time of an existing API endpoint.我是 django-rest-framework 的新手,我有一个项目,我必须优化现有 API 端点的响应时间。 Using django-debug-toolbar, found some ways to use prefetch_related() to lessen the SQL queries.使用 django-debug-toolbar,找到了一些使用 prefetch_related() 来减少 SQL 查询的方法。 The problem is I found that the design of the serializer is to have multiple SerializerMethodField to get its statistics values and using prefetch_related only works on all() but on the second serializer method field with filter() is still being queried for every Class loop.问题是我发现序列化器的设计是有多个 SerializerMethodField 来获取它的统计值,并且使用 prefetch_related 仅适用于 all() 但在第二个序列化器方法字段上仍然会为每个 Class 循环查询 filter() 。 You may see sample code below(this is not the specific code but something like this).您可能会在下面看到示例代码(这不是特定代码,而是类似的代码)。

serializer.py:序列化程序.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:视图.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. 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. For now, making a new model is out of the question so i am stuck on how to properly prefetch the second query request.目前,制作一个新的 model 是不可能的,所以我被困在如何正确预取第二个查询请求上。 Hope you can suggest possible way to resolve this.希望您能提出解决此问题的可能方法。 Thank you in advance guys.提前谢谢你们。

You can annotate the count for the objects with queryset and then pass it through serializer class initialization.您可以使用查询集注释对象的计数,然后将其传递给序列化程序 class 初始化。 Like this:像这样:

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
    )
)

Then you need to remove SerializerMethodField s from your serializer, a simple IntegerField should be suffice to get the data from queryset without addional db hits:然后你需要从你的序列化程序中删除SerializerMethodField s,一个简单的 IntegerField 应该足以从查询集中获取数据而无需额外的数据库命中:

class ClassStatisticsSerializer(ModelBaseSerializer):
    total_sessions = serializers.IntegerField()
    activity_count = serializers.IntegerField()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 django-rest-framework 动态添加 SerializerMethodField 到 Serializer - django-rest-framework add SerializerMethodField to Serializer dynamically 如何在 django-rest-framework 查询集响应中添加注释数据? - how to add annotate data in django-rest-framework queryset responses? 如何根据 django-rest-framework 中的最佳匹配对查询集进行排序? - How to order queryset based on best match in django-rest-framework? django-rest-framework,多表 model inheritance,模型序列化器和嵌套序列化器 - django-rest-framework, multitable model inheritance, ModelSerializers and nested serializers 使用 django-rest-framework 序列化程序检索外键值 - Retrieving a Foreign Key value with django-rest-framework serializers 如何在 Django Rest 框架中使用 SerializerMethodField 进行更新 - How to update with SerializerMethodField in Django Rest Framework Django Rest Framework 如何更新 SerializerMethodField - Django Rest Framework How to update SerializerMethodField 如何使用 django-rest-framework 中的序列化程序将相似数据合并到自定义字段中? - How to merge similar data into a custom field using serializers in django-rest-framework? django-rest-framework:根据请求限制RelatedField查询集 - django-rest-framework : restrict RelatedField queryset according to request 如何使用Django-rest-framework上传多个文件 - How to upload multiple files with django-rest-framework
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM