Django更新嵌套对象时如何将缺失的pk字段添加到序列化器中
解决方案
第一步:修改PlanEventUpdateSerializer配置
默认DRF的ModelSerializer会将模型主键字段设置为只读,反序列化后validated_data不会包含该字段,需要手动显式声明id为可写字段并加入字段列表:
class PlanEventUpdateSerializer(serializers.ModelSerializer): # 显式声明id字段,取消默认只读约束 id = serializers.CharField(max_length=100) class Meta: model = PlanEvent fields = ('id', 'done', 'title')
修改后只要前端提交的events数据中携带每条事件的id,你写的删除对比逻辑就能正常获取item['id']执行判断。
第二步:补充完整update方法逻辑
你当前只写了删除逻辑,建议补充已有事件更新、新增事件的逻辑保证功能完整:
class PlanUpdateSerializer(serializers.ModelSerializer): events = PlanEventUpdateSerializer(many=True) class Meta: model = Plan fields = ('name',) def update(self, instance, validated_data): events_validated_data = validated_data.pop('events') # 先更新Plan主表字段 instance.name = validated_data.get('name', instance.name) instance.save() existing_events = list(instance.events.all()) existing_event_map = {event.id: event for event in existing_events} submitted_event_ids = [item['id'] for item in events_validated_data] # 删除未提交的旧事件 for event in existing_events: if event.id not in submitted_event_ids: event.delete() # 更新已有事件、新增提交的新事件 for event_data in events_validated_data: event_id = event_data['id'] if event_id in existing_event_map: # 更新已存在的事件 event = existing_event_map[event_id] event.done = event_data.get('done', event.done) event.title = event_data.get('title', event.title) event.save() else: # 新增事件,关联当前Plan实例 PlanEvent.objects.create(plan=instance, **event_data) return instance
注意事项
- 前端提交events数组时必须携带对应事件的
id字段,如果是新增的事件也需要生成唯一id同步提交,匹配你模型中PlanEvent.id为手动指定主键的设计 - 如果不需要前端生成新增事件id,可以将
PlanEvent.id的字段属性修改为default=uuid.uuid4, editable=False,对应序列化器中id字段设置为required=False,新增时就不需要传id参数
内容的提问来源于stack exchange,提问作者lr_optim
相关产品推荐
相关产品推荐

