django 使用SerializerMethodField减少序列化程序中的SQL查询数

66bbxpm5  于 2023-01-10  发布在  Go
关注(0)|答案(1)|浏览(139)

我需要使用包含查询的SerializerMethodField优化序列化程序。该查询用于从另一个对象(Event)检索信息,该对象通过主键链接到Sensor对象。

class SiteSensorSerializer(serializers.ModelSerializer):
    issue = serializers.SerializerMethodField()

    class Meta:
        model = Sensor
        fields = ('id', 'label', 'view', 'issue',)

    def get_issue(self, obj):
        return (
            Event.objects.filter(sensor=obj, date_end__isnull=True)
            .order_by('-date_start')
            .exists()
        )

class SiteDeviceSerializer(serializers.ModelSerializer):
    label = DeviceLabelSerializer()
    sensors = SiteSensorSerializer(many=True, read_only=True)
    class Meta:
        model = Device
        fields = ('id', 'name', 'label', 'sensors')

我的问题是对于每个传感器,执行get_issue方法中的查询。
如何减少查询次数?我的视图集:

class SiteViewSet(viewsets.ReadOnlyModelViewSet):
    permission_classes = (permissions.IsAuthenticated,)
    serializer_class = SiteSerializer
    filter_backends = [
        DjangoFilterBackend,
        filters.SearchFilter,
        filters.OrderingFilter,
    ]
    filter_fields = [
        "name",
    ]
    search_fields = ["name"]
    ordering = ["name"]

    def get_queryset(self):
        if self.request.user.is_superuser:
            return (
                Site.objects.all()
                .prefetch_related("devices")
                .prefetch_related("devices__label")
                .prefetch_related("devices__sensors")
            )
        else:
            return (
                Site.objects.filter(devices__users=self.request.user)
                .prefetch_related(
                    Prefetch(
                        "devices",
                        Device.objects.filter(users=self.request.user).select_related(
                            "label"
                        ),
                    )
                )
                .distinct()
                .prefetch_related(
                    Prefetch(
                        "devices__sensors",
                        Sensor.objects.filter(device__users=self.request.user),
                    )
                )
                .distinct()
            )
wwtsj6pe

wwtsj6pe1#

一个小的优化是从get_issue()中删除order_by('-date_start'),因为您正在调用exists(),它只根据QuerySet中是否有超过0个对象返回一个布尔值,因此对QuerySet进行排序没有意义。
get_issue()将如下所示:

def get_issue(self, obj):
    return (
        Event.objects.filter(sensor=obj, date_end__isnull=True)
        .exists()
    )

相关问题