You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Rest Framework中Choices对象不可JSON序列化如何修复

错误原因

报错本质是Python原生Enum类的成员是枚举类型实例,不属于JSON支持的基础数据类型(字符串、数字、布尔值、列表、字典、None),DRF默认的JSON序列化器无法直接处理这类对象。你的代码中Choices.BOOK是枚举实例而非字符串"book",如果generate_url方法的返回值中携带了这个未做值提取的枚举实例,接口返回时就会触发该序列化错误。

修复方法

根据项目场景选以下任意一种方案即可:

  • 单点修改(改动最小,适合枚举使用频次低的场景)
    调用枚举时通过.value属性取出枚举绑定的实际基础值,修改get_url方法的传参逻辑:
    class SomeApiView(APIView):
       def get_url(self, some_id):
         # 取出Choices.BOOK对应的实际字符串值"book"传入
         return generate_url(Choices.BOOK.value, some_id)
    
       def get(self,request):
         id = request.query_params.get("some_id")
         result_url = self.get_url(id)
         return Response({'result_url': result_url})
    
  • 全局兼容(适合项目中大量使用枚举的场景,一劳永逸)
    自定义支持Enum序列化的JSON渲染器,全局替换DRF默认渲染器,后续所有枚举实例会自动提取值做序列化,不需要每次手动写.value:
    1. 编写自定义渲染器:
    from rest_framework.renderers import JSONRenderer
    from enum import Enum
    
    class EnumCompatibleJSONRenderer(JSONRenderer):
        def default(self, obj):
            if isinstance(obj, Enum):
                return obj.value
            return super().default(obj)
    
    1. 在项目settings.py的DRF配置项中注册该渲染器:
    REST_FRAMEWORK = {
        'DEFAULT_RENDERER_CLASSES': [
            # 替换为你自定义渲染器的实际项目路径
            'your_project.path.to.EnumCompatibleJSONRenderer',
            'rest_framework.renderers.BrowsableAPIRenderer',
        ]
    }
    
  • 框架原生方案(推荐Django 3.0+版本使用)
    直接替换原生Enum为Django内置的TextChoices类型,该类型继承自字符串,既可以作为枚举使用,本身也是合法的字符串值,DRF可以直接序列化不需要额外处理,同时原生兼容Django模型的choices配置:
    from django.db import models
    
    class Choices(models.TextChoices):
      BOOK="book"
      MOVIE="movie"
      GAME="game"
    
    替换枚举定义后,原有业务代码不需要做任何修改即可正常运行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 01:21:34