在Django Rest Framework的CourseViewSet中更新关联Prerequisite
实现DRF中课程关联前置条件的嵌套更新(类似Admin TabularInline)
当前你的序列化器仅支持读取关联的Prerequisite数据,无法在更新Course时同步修改关联的前置条件。要实现类似Django Admin TabularInline的关联更新,无需单独创建Prerequisite视图,只需调整序列化器并添加更新逻辑即可,具体步骤如下:
1. 修改序列化器,支持嵌套读写
替换原CourseSerializer中的SerializerMethodField为可写的嵌套序列化器,并添加update方法处理关联数据的增删改:
class CourseSerializer(serializers.ModelSerializer): # 替换只读的SerializerMethodField为可写的嵌套序列化器 prerequisite = PrerequisiteSerializer(many=True) class Meta: model = models.Course fields = "__all__" def update(self, instance, validated_data): # 提取传入的前置条件数据,若无则跳过关联更新 prerequisites_data = validated_data.pop('prerequisite', None) # 先更新Course自身的字段 instance = super().update(instance, validated_data) if prerequisites_data: # 获取当前课程已有的所有前置条件ID existing_prereq_ids = instance.course_prerequisite.values_list('id', flat=True) # 收集传入数据中带ID的前置条件ID incoming_prereq_ids = [item['id'] for item in prerequisites_data if 'id' in item] # 删除不在传入列表中的前置条件(模拟TabularInline的删除操作) instance.course_prerequisite.exclude(id__in=incoming_prereq_ids).delete() # 遍历传入数据,更新现有前置条件或创建新的 for prereq_data in prerequisites_data: prereq_id = prereq_data.get('id') if prereq_id and prereq_id in existing_prereq_ids: # 存在ID则更新对应前置条件 Prerequisite.objects.filter(id=prereq_id, course=instance).update(**prereq_data) else: # 无ID则创建新的前置条件关联到当前课程 Prerequisite.objects.create(course=instance, **prereq_data) return instance
2. 调整视图的update方法(如需要)
如果你的CourseViewSet继承自ModelViewSet,默认的update方法已能满足需求,无需额外修改。如果是自定义的update方法,确保传递请求数据并启用部分更新:
def update(self, request, pk=None): course = get_object_or_404(Course, slug=pk) # partial=True允许只更新部分字段 serializer = serializers.CourseSerializer(instance=course, data=request.data, partial=True) serializer.is_valid(raise_exception=True) serializer.save() return Response(serializer.data, status=status.HTTP_200_OK)
3. 测试更新请求
发送PATCH请求到课程详情接口,请求体示例如下(更新ID为1的Prerequisite标题):
{ "prerequisite": [ { "id": 1, "title": "Updated Introduction to Python Basics" } ] }
这样就能在更新课程的同时,同步修改关联的Prerequisite数据,实现类似Admin TabularInline的关联更新效果。
内容的提问来源于stack exchange,提问作者Nikolat
相关产品推荐
相关产品推荐

