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:- 编写自定义渲染器:
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)- 在项目
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
相关产品推荐
相关产品推荐

