在Django ModelSerializer中通过中间表实现多对多增改并保存Fee字段
解决Django序列化器中多对多中间表fee字段的保存问题
你的问题核心是没正确处理嵌套在memberships数据里的fee字段——其实每个memberships项里已经包含了person和fee,不需要从validated_data里单独提取。我们只需要在创建/更新Membership实例时,把这两个字段一起传入即可。
下面是修正后的完整序列化器代码:
from rest_framework import serializers from .models import Group, Membership, Person class GroupMembershipSerializer(serializers.ModelSerializer): class Meta: model = Membership fields = ('person', 'fee', ) class GroupCreateSerializer(serializers.ModelSerializer): memberships = GroupMembershipSerializer(many=True, required=False) def create(self, validated_data): # 取出嵌套的memberships数据,没有则设为空列表避免报错 memberships_data = validated_data.pop('memberships', []) # 创建Group主实例 group = Group.objects.create(**validated_data) # 循环创建中间表关联,同时传入person和fee字段 for membership in memberships_data: Membership.objects.create( group=group, person=membership['person'], fee=membership['fee'] ) return group def update(self, instance, validated_data): # 取出嵌套的memberships数据 memberships_data = validated_data.pop('memberships', None) # 更新Group自身的字段 for attr, value in validated_data.items(): setattr(instance, attr, value) instance.save() # 只有当传入memberships数据时,才删除原有关联并重建 if memberships_data is not None: Membership.objects.filter(group=instance).delete() for membership in memberships_data: Membership.objects.create( group=instance, person=membership['person'], fee=membership['fee'] ) return instance class Meta: model = Group fields = ('id', 'name', 'memberships') # 显式声明字段更清晰
关键修正点说明:
Create方法:
- 移除了错误的
fee = validated_data.pop('fee')操作,直接从每个membership项里获取fee - 给
pop方法加了默认值,避免没有传入memberships时抛出KeyError
- 移除了错误的
Update方法:
- 简化了Group字段的更新逻辑,用循环直接遍历设置属性
- 同样在创建新的Membership时传入
fee字段 - 增加判断逻辑,只有当传入memberships数据时才执行删除重建操作,更严谨
Meta类:
- 显式声明序列化字段,包括
id、name和memberships,让序列化器的作用范围更明确
- 显式声明序列化字段,包括
现在你发送类似这样的请求时,fee字段就会被正确保存到中间表了:
{ "name": "技术团队", "memberships": [ {"person": 1, "fee": 150}, {"person": 2, "fee": 200} ] }
内容的提问来源于stack exchange,提问作者Mehdi
相关产品推荐
相关产品推荐

