sqlalchemy:2.0.25 蒸馏器:1.13.1 蟒蛇:3.11
alembic revision --autogenerate -m "initial migration"
在迁移中创建空的 upgrade
和 downgrade
代码。
如下所示,我在与基类不同的文件中有两个模型类。
我的 alembic/env.py 按照他们的文档说明导入我的基类,以便它可以访问元数据。在空数据库上,这应该会生成升级代码来创建 Order 和 Item 表,但似乎没有从 Base.metadata 中找到这些类。 1. 凭直觉,我将这些类的导入放入 env.py 中(如下所示),然后正确地自动生成迁移。 2. 作为一种替代解决方法,我还发现将所有模型与 Base 一起放入一个大文件中可以完整生成。
解决方法 1 还可以,但随着模型类数量的增加,会有点麻烦。解决方法 2 是不可接受的。
是否有更优雅和可靠的方法让它找到所有模型类以进行自动生成?
#models.base.py
from sqlalchemy.orm import DeclarativeBase
class Base(DeclarativeBase):
pass
#models.order.py
from models.base import Base
class Order(Base):
__tablename__ = "Order"
id: Mapped[int] = mapped_column(primary_key=True)
description: Mapped[Optional[str]]
items: Mapped[List["Item"]] = relationship(back_populates="order")
#models.item.py
from models.base import Base
class Item(Base):
__tablename__ = "Item"
id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
description: Mapped[str] = mapped_column(String(255))
order_id: Mapped[int] = mapped_column(ForeignKey("Order.id"))
order: Mapped["Order"] = relationship(back_populates="items")
#alembic/env.py (excerpt)
from models.base import Base
from models.order import Order # not prescribed by doc but makes it work
from models.item import Item # same as above
target_metadata = Base.metadata
您可以在单独的文件中定义基类,例如
base_class.py
,在模型定义中重用它,例如order.py
并将所有模型导入到 base.py
文件中以在 alembic env.py
中使用。
例如
# db.base_class.py
from typing import Any
from sqlalchemy.ext.declarative import as_declarative, declared_attr
@as_declarative()
class Base:
id: Any
__name__: str
# Generate __tablename__ automatically
@declared_attr
def __tablename__(cls) -> str:
return cls.__name__.lower()
# models.order.py
from db.base_class import Base
class Order(Base):
id: Mapped[int] = mapped_column(primary_key=True)
description: Mapped[Optional[str]]
items: Mapped[List["Item"]] = relationship(back_populates="order")
# models.base.py
from db.base_class import Base # noqa
from models.order import Order # noqa
from models.item import Item # noqa
如果创建迁移脚本时出现错误,可以在模型的init.py中导入模型
# models.__init__.py
from .order import Order # noqa
from .item import Item # noqa
有了这个,您不必每次创建模型时都更新 alembic.env.py,但您必须在
models.base.py
中导入它,以及 Order 和 Item。