如何在Django REST Framework序列化器中正确展示带中间表的ManyToMany字段
错误原因
你使用through参数自定义多对多关联的中间表后,SalesAction模型的medicines字段默认返回的是关联的Medicine模型实例集合,并不是中间表SalesActionMedicine的实例集合。你将中间表对应的序列化器直接绑定在medicines字段上时,序列化器会尝试用中间表的字段(如sales_action)去匹配Medicine实例的属性,自然就抛出属性不存在的错误。
解决方案
方案1:需要返回中间表的额外字段(数量类型、数量)
这是符合你需求的常用方案,修改序列化器如下:
- 优化中间表序列化器,可嵌套序列化药品基础信息,同时去掉冗余的
sales_action字段
class SalesActionMedicineSerializer(serializers.ModelSerializer): # 嵌套序列化药品详情,按需配置需要返回的药品字段 class MedicineSerializer(serializers.ModelSerializer): class Meta: model = Medicine fields = ('id', 'name') # 可自行添加药品的其他字段 medicine = MedicineSerializer(read_only=True) class Meta: model = SalesActionMedicine fields = ('medicine', 'quantity_type', 'quantity')
- 修改
SalesAction序列化器,通过source指定获取中间表的反向关联数据
class SalesActionSerializer(serializers.ModelSerializer): # source指定为中间表的默认反向关联名,默认规则是中间表名小写+_set medicines = SalesActionMedicineSerializer(source='salesactionmedicine_set', many=True, read_only=True) class Meta: model = SalesAction fields = ('sales_representative', 'doctor', 'remark', 'date', 'medicines')
方案2:仅需要返回药品基础信息,不需要中间表字段
如果不需要数量等中间表字段,直接给medicines绑定药品序列化器即可:
class MedicineSerializer(serializers.ModelSerializer): class Meta: model = Medicine fields = ('id', 'name') # 按需配置字段 class SalesActionSerializer(serializers.ModelSerializer): medicines = MedicineSerializer(many=True, read_only=True) class Meta: model = SalesAction fields = ('sales_representative', 'doctor', 'remark', 'date', 'medicines')
性能优化提示
- 查询
SalesAction数据时建议使用prefetch_related预加载关联数据,避免N+1查询问题,示例:
queryset = SalesAction.objects.prefetch_related('salesactionmedicine_set__medicine').all()
内容的提问来源于stack exchange,提问作者Dhia Shalabi
相关产品推荐
相关产品推荐

