You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Django REST Framework获取嵌套结构的设备关联测量数据?

问题需求

需要获取嵌套结构的JSON数据:

[
    {
        "deviceid": 4,
        "devicename": "###",
        "device_measurement": {
            "deviceid": 4,
            "measurement": "31.8"
        }
    }
]

但目前接口返回的是两个平级对象的数组:

[
    {
        "deviceid": 4,
        "devicename": "###"
    },
    {
        "deviceid": 4,
        "measurement": "31.8"
    }
]

当前实现代码

Views

from itertools import chain

class RetrieveSpecificDevicesView(APIView):
    permission_classes = [permissions.IsAuthenticated]
    serializer_class = SpecificDeviceSerializer

    def post(self, request):
        if self.request.method == 'POST':       
            serializer = SpecificDeviceSerializer(data=request.data)

            if serializer.is_valid():
                obj1= Devices.objects.using('@@@').filter(deviceid=serializer.data.get("deviceid"))
                obj2= Measurements.objects.using('@@@').filter(deviceid=serializer.data.get("deviceid"))
                dats= chain(obj1, obj2)
                data = serializers.serialize('json', dats)
                return HttpResponse(data, content_type="application/json")

            return JsonResponse(serializer.error, status=status.HTTP_201_CREATED)

Serializer

class SpecificDeviceSerializer(serializers.Serializer):
    deviceid = serializers.CharField(required=True)

class MeasurmentsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Measurements
        fields = ('measurementid','measurement')

Models

注:模型关联关系为Devices与Measurements是一对多(一个设备对应多条测量记录)


尝试修改后的错误代码及问题

尝试通过Serializer实现嵌套返回时,出现错误:Got AttributeError when attempting to get a value for field devicesname on serializer SpecificDeviceSerializer

修改后的Views

class RetrieveSpecificDevicesView(APIView):
    permission_classes = [permissions.IsAuthenticated]
    serializer_class = SpecificcDeviceSerializer
    
    def post(self, request):
        if self.request.method == 'POST':       
            data = self.serializer_class.get_device(self, obj=request.data)
            user = SpecificDeviceSerializer(data)
            return HttpResponse(user)

修改后的Serializers

class SpecificDeviceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Devices
        fields = ( 'deviceid', 'devicename') 

class SpecificcDeviceSerializer(serializers.ModelSerializer):
    def get_device(self, obj):
        device =  Devices.objects.using('@@@').filter(deviceid=obj.get("deviceid"))
        return device
    
    class Meta:
        model = Devices
        fields = ( 'deviceid', 'devicename') 

解决方案

步骤1:定义嵌套序列化器

利用DRF的嵌套序列化器特性,直接在设备序列化器中关联测量数据的序列化逻辑:

class MeasurementSerializer(serializers.ModelSerializer):
    class Meta:
        model = Measurements
        fields = ('deviceid', 'measurement')  # 只保留需要返回的字段

class DeviceWithMeasurementSerializer(serializers.ModelSerializer):
    # 关联单条测量记录(比如最新的第一条)
    device_measurement = MeasurementSerializer(source='measurements.first', read_only=True)
    # 若需要返回多条测量记录,修改为:
    # device_measurement = MeasurementSerializer(source='measurements', many=True, read_only=True)

    class Meta:
        model = Devices
        fields = ('deviceid', 'devicename', 'device_measurement')

注:如果Models中Devices和Measurements的外键未设置related_name,默认反向关联名为measurements_set,需将source='measurements.first'改为source='measurements_set.first'

步骤2:修改View逻辑

无需合并两个QuerySet,直接查询设备并预取关联数据,用嵌套序列化器处理输出:

class RetrieveSpecificDevicesView(APIView):
    permission_classes = [permissions.IsAuthenticated]
    serializer_class = SpecificDeviceSerializer

    def post(self, request):
        serializer = SpecificDeviceSerializer(data=request.data)
        if serializer.is_valid():
            device_id = serializer.data.get("deviceid")
            # 预取关联测量数据,避免N+1查询性能问题
            devices = Devices.objects.using('@@@').filter(deviceid=device_id).prefetch_related('measurements')
            # 用嵌套序列化器序列化数据
            response_serializer = DeviceWithMeasurementSerializer(devices, many=True)
            return Response(response_serializer.data, status=status.HTTP_200_OK)
        # 修正拼写错误:serializer.error → serializer.errors,验证失败返回400状态码
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

关键说明

  1. 借助DRF嵌套序列化器,直接在设备序列化器中包含测量数据的序列化规则
  2. 使用prefetch_related优化反向关联查询,提升接口性能
  3. 可根据需求选择返回单条或多条测量记录,灵活调整序列化器配置

内容的提问来源于stack exchange,提问作者Denis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 14:45:40