You need to enable JavaScript to run this app. DRF序列化带url的django-mptt树结构Section模型时报OrderedDict无uuid错误
优惠活动
大模型
产品
解决方案
定价
更多

DRF序列化带url的django-mptt树结构Section模型时报OrderedDict无uuid错误

报错根源定位

报错的触发链路和你观察到的现象完全对应:

  • DRF 的超链接url字段生成接口地址时,必须从关联的模型实例上读取lookup_field对应的属性值,比如你配置的uuid
  • 你当前手写的children = serializers.ListField(source='get_children', child=RecursiveField())实现,没有将原始的Section模型实例正确透传到每一层递归序列化的上下文里
  • 当递归处理到子节点的url字段时,字段拿到的待处理对象已经是被部分序列化后的collections.OrderedDict结构,而非Section模型实例,自然无法读取到uuid或pk属性,直接抛出AttributeError
  • 只要移除序列化器里的url字段,字段处理时不需要读取模型实例的主键值生成链接,报错就会完全消失,这也和你验证过的现象一致。
修复步骤

1. 替换手写嵌套字段的实现

不要用ListField包裹RecursiveField,这种写法会切断模型实例到递归序列化器的传递链路。直接调整嵌套字段的定义,适配drf-writable-nested和django-mptt的处理规则:

# serializers.py
class SectionSerializer(UniqueFieldsMixin, WritableNestedModelSerializer):
    # 直接将RecursiveField绑定到mptt的get_children方法,移除外层ListField包裹
    children = RecursiveField(many=True, source='get_children')

    class Meta:
        model = Section
        fields = ['url', 'uuid', 'name', 'children']
        extra_kwargs = {
            'url': {
                'lookup_field': 'uuid',
                # 显式指定路由名,避免嵌套层找不到视图配置
                'view_name': 'section-detail'
            },
        }

2. 调整视图继承逻辑

你当前的视图同时继承generics.RetrieveUpdateDestroyAPIView和viewsets.GenericViewSet,存在类继承顺序冲突,容易导致序列化器生成url字段时上下文匹配异常。建议调整为标准的视图集写法:

# views.py
from rest_framework import viewsets

class SectionDetailViewSet(viewsets.RetrieveUpdateDestroyAPIViewSet):
    queryset = Section.objects.all()
    serializer_class = SectionSerializer
    lookup_field = 'uuid'

3. (可选)上下文兼容补丁

如果修复后递归层依然出现实例读取错误,可以在序列化器里增加手动透传逻辑,确保每一层的递归序列化器都能拿到完整的请求上下文:

class SectionSerializer(UniqueFieldsMixin, WritableNestedModelSerializer):
    # ... 原有字段配置保持不变
    def to_representation(self, instance):
        # 将当前模型实例和上下文透传给递归字段
        for field in self.fields.values():
            if isinstance(field, RecursiveField):
                field.context = self.context
        return super().to_representation(instance)
效果验证

修复完成后,不管是根节点还是所有递归嵌套的子节点,url字段在生成链接时都能拿到对应的Section模型实例,正确读取实例上的uuid属性拼接接口地址,不会再出现将OrderedDict当模型实例读取属性的报错。

内容的提问来源于stack exchange,提问作者vit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.07 02:36:08