具有整数值的 SQLAlchemy 枚举类型字段

SQLAlchemy Enum type field with integer value

有一个事件模型,我想在其中添加一个 memebers_count 字段来指示参与者的数量。用户将从 select 形式生成单个 selection。我为此使用 Enum 类型。模型看起来像这样

class MembersQuantity(enum.Enum):
    two = 2
    three = 3
    four = 4
    five = 5
    six = 6
    ...
    nineteen = 19
    twenty = 20
    thirty = 30
    forty = 40
    fifty = 50
    unlimited = 1000

events = Table(
    "events",
    metadata,
    Column("id", Integer(), primary_key=True),
    ...
    Column("members_count", Enum(MembersQuantity, values_callable=lambda obj: [e.value for e in obj]),
           nullable=False,
           default=MembersQuantity.two.value,
           server_default=MembersQuantity.two.value),
    ....

输入时控制台出现错误

  File "/home/jekson/Projects/own/wplay/./models/events.py", line 64, in <module>
    Column("members_count", Enum(MembersQuantity, values_callable=lambda obj: [e.value for e in obj]),
  File "<string>", line 2, in __init__
  File "/home/jekson/virtualenvs/wplay/lib/python3.9/site-packages/sqlalchemy/util/deprecations.py", line 139, in warned
    return fn(*args, **kwargs)
  File "/home/jekson/virtualenvs/wplay/lib/python3.9/site-packages/sqlalchemy/sql/sqltypes.py", line 1383, in __init__
    self._enum_init(enums, kw)
  File "/home/jekson/virtualenvs/wplay/lib/python3.9/site-packages/sqlalchemy/sql/sqltypes.py", line 1425, in _enum_init
    length = max(len(x) for x in self.enums)
  File "/home/jekson/virtualenvs/wplay/lib/python3.9/site-packages/sqlalchemy/sql/sqltypes.py", line 1425, in <genexpr>
    length = max(len(x) for x in self.enums)
TypeError: object of type 'int' has no len()

我认为问题是 [e.value for e in obj] 应该是 str 而不是 int 并将其替换为 [str(e.value) for e in obj] 但得到另一个错误

sqlalchemy.exc.ArgumentError: Argument 'arg' is expected to be of the type '<class 'str'>' or '<class 'sqlalchemy.sql.elements.ClauseElement'>' or '<class 'sqlalchemy.sql.elements.TextClause'>', got '<class 'int'>'

怎么了?

问题是你想坚持什么? two 或 2 或 <MembersQuantity.two: 2>?

SQLAlchemy docs 状态:

Above, the string names of each element, e.g. “one”, “two”, “three”, are persisted to the database; 
the values of the Python Enum, here indicated as integers, are not used;
the value of each enum can therefore be any kind of Python object whether or not it is persistable.

所以如果你有枚举的整数值,你可能应该有这样的东西:

    Column(
       "members_count", 
       Enum(MembersQuantity),
       nullable=False,
       default=MembersQuantity.two.name,
       server_default=MembersQuantity.two.name
    )

name 属性是 two,而 value 属性在你的例子中是 2。但是你只坚持 left-hand 侧弦。 仅当您想要保留值而不是名称时才应使用 values_callable,但文档还指出:value_callables - a callable which will be passed the PEP-435 compliant enumerated type, which should then return a list of string values to be persisted。所以只有当它是一个字符串时你才能持久化值。

这里有一个可能有用的主题: