Django中如何扩展引用枚举而非外键的字段?
解决枚举类型字段的扩展序列化问题
错误原因
你用ModelSerializer序列化Python标准库的Enum类导致报错——ModelSerializer是为Django模型设计的,依赖模型的_meta属性,但Enum类没有这个属性,因此触发AttributeError: _meta。
解决方案
1. 修正模型字段定义
先把枚举类和模型字段的关联改正确,用choices参数绑定枚举的键值对:
from enum import Enum from django.db import models class StatoCivile(Enum): S = "单身" M = "已婚" D = "离异" class PfPersona(models.Model): stato_civile = models.CharField( max_length=1, # 将枚举成员转为choices格式:(存储值, 显示值) choices=[(member.name, member.value) for member in StatoCivile], blank=True, null=True, db_column='stato_civile' ) # 其他字段...
2. 编写枚举专用序列化器
不用ModelSerializer,改用基础的Serializer来序列化枚举实例:
from rest_framework import serializers class StatoCivileSerializer(serializers.Serializer): # 枚举的键(对应数据库存储值,如"S") key = serializers.CharField(source='name') # 枚举的显示值(如"单身") label = serializers.CharField(source='value')
3. 调整主序列化器的扩展逻辑
因为枚举字段不是外键关联,需要手动处理扩展逻辑。假设你用的是rest_framework_expandable的ExpandableSerializerMixin,修改主序列化器如下:
from rest_framework_expandable import ExpandableSerializerMixin class PfPersonaSerializer(ExpandableSerializerMixin, serializers.ModelSerializer): expandable_fields = { "otherfield": OtherFieldSerializer, "stato_civile": StatoCivileSerializer } # 自定义扩展字段的获取方法 def get_stato_civile(self, obj): if not obj.stato_civile: return None # 从数据库存储的键获取枚举实例 enum_instance = StatoCivile[obj.stato_civile] return StatoCivileSerializer(enum_instance).data class Meta: model = PfPersona fields = ["id", "stato_civile", "otherfield", ...]
4. 测试调用
现在访问http://localhost:8000/pf/?expand=stato_civile,就能得到包含枚举扩展数据的响应,示例响应:
{ "id": 1, "stato_civile": { "key": "S", "label": "单身" }, "otherfield": {...} }
替代方案:手动处理扩展参数
如果不用扩展序列化器Mixin,也可以在主序列化器的to_representation方法里手动判断expand参数:
class PfPersonaSerializer(serializers.ModelSerializer): class Meta: model = PfPersona fields = ["id", "stato_civile", "otherfield", ...] def to_representation(self, instance): data = super().to_representation(instance) expand_params = self.context['request'].query_params.getlist('expand', []) if 'stato_civile' in expand_params and instance.stato_civile: enum_instance = StatoCivile[instance.stato_civile] data['stato_civile'] = StatoCivileSerializer(enum_instance).data return data
内容的提问来源于stack exchange,提问作者Andrea Balestri
相关产品推荐
相关产品推荐

