Skip to main content

使 Python 枚举成为 SQLAlchemy 表,支持 Alembic 迁移

项目描述

SQLAlchemy通过其列类型sqlalchemy.Enum具有内置的enum.Enum支持。但是,此类型依赖于后端的枚举类型或检查约束。这两个都是不可变对象,修改起来很麻烦(只有 PostgreSQL 支持向枚举类型添加值,即使那样它也不支持删除它们)。

在数据库中支持枚举的另一种常用模式是通过反映枚举值的专用表。这需要在每次修改枚举时更新表,但这样做比替换类型要简单得多。

此包允许您直接从 Python 枚举类创建枚举表和引用该表​​的列。它还与 Alembic 交互,以自动将INSERTDELETE语句添加到您自动生成的迁移脚本中。

何时使用

  1. 仅适用于 Python 的枚举类,或者至少一个行为类似于enum.Enum的类。不适用于任意条目的集合。

  2. 仅适用于 SqlAlchemy 的声明式 ORM 系统。如果你只使用 SqlAlchemy Core...处理它

  3. 更好地用于频繁更新的枚举类。

  4. 不要与在 Alembic中提供 op.enum_insertop.enum_delete操作的其他包一起使用。

如何使用 SqlAlchemy

import enum
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base

import enumtables as et

# Create the Python enumeration class
class MyEnum(enum.Enum):
    HELLO = "HELLO"
    WORLD = "WORLD"

Base = declarative_base()

# Create the enumeration table
# Pass your enum class and the SQLAlchemy declarative base to enumtables.EnumTable
MyEnumTable = et.EnumTable(MyEnum, Base)

# Create a model class that uses the enum
class MyModel(Base):
    __tablename__ = "my_model"
    # Pass the enum table (not the enum class) to enumtables.EnumColumn
    # It replaces sqlalchemy.Column, but aside from the enum table,
    # it can take the same parameters.
    # It will automatically create a ForeignKeyConstraint referencing the enum table.
    enum_value = et.EnumColumn(MyEnumTable, primary_key = True)

    # When valued (on an instance of MyModel), enum_value will be an instance of MyEnum.

首先,EnumTable工厂采用枚举类和声明性基类来创建实际的 ORM 类。然后将此 ORM 类传递给EnumColumn类以创建链接到枚举表的列。该列的行为就像它具有 SqlAlchemy 自己的Enum类型一样。

在实现方面,EnumTable不是一个类,它是一个工厂函数,它执行 Python 黑魔法来创建声明性基础的子类,并将其设置为包含枚举项的 DB 表(实际上它只有一列item_id字符串类型)。

EnumColumn是 SqlAlchemy 的Column的子类,它使用自定义类型和枚举表的外键进行初始化。

如何与 Alembic 一起使用

首先添加:

import enumtables

env.py文件的开头,然后在script.py.mako文件的导入中添加同一行。该包使用 Alembic 的标准挂钩来处理迁移生成。

之后不要忘记查看迁移。特别要确保,如果表之前不存在,则op.enum_insert命令位于相应的op.create_table命令之后

其他用途

直接使用枚举表类

枚举表类的行为类似于任何 SqlAlchemy ORM 类:

enum_query = session.query(MyEnumTable)
result = enum_query.first()

# The column item_id stores the name of the enum item as a string
enum_name = result.item_id

向枚举表添加更多列

传递给EnumTable工厂的任何关键字参数都将成为表类的成员。这意味着,您可以像定义通常的 ORM 类一样传递任何内容(如列):

BetterEnumTable = et.EnumTable(
    MyEnum,
            Base,

    # tablename is turned into __tablename__
    tablename = "better_enum",

    # Let's add a new column!
    order = sa.Column(sa.Integer, nullable = False),

    # And since it's an ordering number, let's make it unique too.
    __table_args__ = (
        sa.UniqueConstraint('order'),
    ),
)

项目详情


下载文件

下载适用于您平台的文件。如果您不确定要选择哪个,请了解有关安装包的更多信息。

源分布

SqlAlchemy Enum Tables-1.1.0.tar.gz (6.3 kB 查看哈希

已上传 source

内置分布

SqlAlchemy_Enum_Tables-1.1.0-py3-none-any.whl (7.1 kB 查看哈希

已上传 py3