如何通过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)
关键说明
- 借助DRF嵌套序列化器,直接在设备序列化器中包含测量数据的序列化规则
- 使用
prefetch_related优化反向关联查询,提升接口性能 - 可根据需求选择返回单条或多条测量记录,灵活调整序列化器配置
内容的提问来源于stack exchange,提问作者Denis
相关产品推荐
相关产品推荐

