Django如何在GET请求返回JSON中可选包含模型关联外键设备列表
解决方案
需求1:GET请求固定返回用户关联的设备列表
首先可以先调整模型的外键配置,给反向关联设置更易读的名称,修改Device模型的user字段:
class Device(models.Model): description = models.CharField(max_length=200) location = models.CharField(max_length=200) max_energy_consumption = models.FloatField() # 注意原字段名拼写多了一个u,建议修正 avg_energy_consumption = models.FloatField() # 新增related_name参数,后续通过user.devices即可获取关联设备 user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, related_name='devices')
之后修改UserSerializer,嵌入设备序列化器即可:
class UserSerializer(serializers.ModelSerializer): # 关联设备列表,many=True表示一对多关联,read_only=True表示仅用于返回,不参与写入校验 devices = DeviceSerializer(many=True, read_only=True) class Meta: model = User fields = '__all__'
修改完成后调用用户GET接口,返回结果就会自动包含对应用户的所有设备列表。
需求2:按需控制关联设备字段返回
更灵活的实现方式是准备两套序列化器,根据请求参数动态切换,同时优化查询性能避免N+1问题:
第一步:定义两套序列化器
# 基础用户序列化器,仅返回用户核心字段 class BaseUserSerializer(serializers.ModelSerializer): class Meta: model = User fields = ['id', 'name', 'birth_date', 'address'] # 扩展序列化器,额外返回关联设备列表 class UserWithDeviceSerializer(BaseUserSerializer): devices = DeviceSerializer(many=True, read_only=True) class Meta(BaseUserSerializer.Meta): fields = BaseUserSerializer.Meta.fields + ['devices']
第二步:修改UserViewSet,动态切换序列化器
class UserViewSet(ModelViewSet): queryset = User.objects.all() serializer_class = BaseUserSerializer # 默认返回基础用户信息 # 重写方法,根据请求参数选择序列化器 def get_serializer_class(self): if self.request.query_params.get('include_devices') == 'true': return UserWithDeviceSerializer return super().get_serializer_class() # 重写查询集,需要返回设备时提前预加载数据,避免N+1查询性能问题 def get_queryset(self): queryset = super().get_queryset() if self.request.query_params.get('include_devices') == 'true': queryset = queryset.prefetch_related('devices') return queryset
调用示例
- 普通请求返回基础用户信息:
GET /users/、GET /users/1/ - 携带参数返回带设备的用户信息:
GET /users/?include_devices=true、GET /users/1/?include_devices=true
内容的提问来源于stack exchange,提问作者Oros Tom
相关产品推荐
相关产品推荐

