在项目中使用枚举的时候你是否会存在以下问题:
- 定义泛滥,用类?用mapping?
- 多端定义,服务端和客户端都定义一遍
- 中英混杂
自定义枚举类
一般情况我们用 Enum 和 IntEnum 定义枚举类,如果是服务端返回枚举的话,还要定义一个枚举的中英映射关系。现在我想实现这3个需求:
- 获取某个枚举全部属性的中英映射字典
- 获取某个枚举全部属性的options列表作为前端下拉选项
- 获取某个枚举属性的属性名、属性值、中文描述
通过重写python内置枚举类来实现这一需求。
from enum import Enum, IntEnum
class EnumPro(Enum):
def __new__(cls, value, desc):
obj = object.__new__(cls)
obj._value_ = value
obj.desc = desc
return obj
@classmethod
def mappings(cls):
return {c._value_: c.desc for c in cls}
@classmethod
def options(cls):
return [{"name": c.desc, "value": c.value} for c in cls]
class IntEnumPro(IntEnum):
def __new__(cls, value, desc):
obj = int.__new__(cls, value)
obj._value_ = value
obj.desc = desc
return obj
@classmethod
def mappings(cls):
return {c._value_: c.desc for c in cls}
@classmethod
def options(cls):
return [{"name": c.desc, "value": c.value} for c in cls]
class StateEnum(EnumPro):
ENABLED = "enabled", '启用'
DISABLED = "disabled", '禁用'
DELETED = "deleted", '删除'
class OrderState(IntEnumPro):
CANCELLED = -1, "已取消"
UNPAID = 0, "未支付"
PAID = 1, "已支付"
print(StateEnum.ENABLED.name) # ENABLED
print(StateEnum.ENABLED.value) # enabled
print(StateEnum.ENABLED.desc) # 启用
print(OrderState.mappings()) # {-1: '已取消', 0: '未支付', 1: '已支付'}
print(OrderState.options()) # [{'name': '已取消', 'value': -1}, {'name': '未支付', 'value': 0}, {'name': '已支付', 'value': 1}]
python中还可以用 MappingProxyTyp 定义不可变字典
STATE_MAP = MappingProxyType(
{
"enabled": "启用",
"disabled": "禁用",
}
)
如何选择?
数据库中可以用smallint、varchar、enum类型存储枚举字段。
如果枚举属性不超过20个,建议用smallint类型,因为smallint只占用2字节;超过20个可以用字符串类型,利于业务上的拓展和理解,不过具体还是得根据实际业务来决定,不建议用数据库的enum类型,删除或修改会很麻烦。