模型和表

使用 db.Model 类定义模型,或使用 db.Table 类创建表。两者都处理 Flask-SQLAlchemy 的绑定键,以与特定引擎关联。

初始化基类

SQLAlchemy 2.x 为您的模型提供了多个可能的基类:DeclarativeBaseDeclarativeBaseNoMeta

创建这些类的子类

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm import DeclarativeBase

class Base(DeclarativeBase):
  pass

如果需要,您可以通过添加 MappedAsDataclass 作为附加父类,来启用 SQLAlchemy 对数据类的原生支持

from sqlalchemy.orm import DeclarativeBase, MappedAsDataclass

class Base(DeclarativeBase, MappedAsDataclass):
  pass

您可以选择使用自定义 MetaData 对象构造 SQLAlchemy 对象。这允许您指定自定义约束 命名约定。这使得约束名称一致且可预测,在使用迁移时非常有用,如 Alembic 所述。

from sqlalchemy import MetaData

class Base(DeclarativeBase):
    metadata = MetaData(naming_convention={
        "ix": 'ix_%(column_0_label)s',
        "uq": "uq_%(table_name)s_%(column_0_name)s",
        "ck": "ck_%(table_name)s_%(constraint_name)s",
        "fk": "fk_%(table_name)s_%(column_0_name)s_%(referred_table_name)s",
        "pk": "pk_%(table_name)s"
    })

初始化扩展

定义基类后,使用 SQLAlchemy 构造函数创建 db 对象。

db = SQLAlchemy(model_class=Base)

定义模型

请参阅 SQLAlchemy 的 声明文档,以获取有关以声明方式定义模型类的完整信息。

子类化 db.Model 以创建模型类。与普通的 SQLAlchemy 不同,如果未设置 __tablename__ 且定义了主键列,则 Flask-SQLAlchemy 的模型将自动生成表名。

from sqlalchemy.orm import Mapped, mapped_column

class User(db.Model):
    id: Mapped[int] = mapped_column(primary_key=True)
    username: Mapped[str] = mapped_column(unique=True)
    email: Mapped[str]

定义模型不会在数据库中创建它。在定义模型后,使用 create_all() 创建模型和表。如果您在子模块中定义模型,则必须导入它们,以便在调用 create_all 之前 SQLAlchemy 知道它们。

with app.app_context():
    db.create_all()

定义表

有关定义表对象的完整信息,请参阅 SQLAlchemy 的表文档

创建db.Table的实例以定义表。该类采用表名,然后采用任何列和其他表部分,例如列和约束。与普通的 SQLAlchemy 不同,metadata参数不是必需的。将根据bind_key参数选择元数据,或使用默认值。

直接创建表的一个常见原因是在定义多对多关系时。关联表不需要自己的模型类,因为它将通过相关模型上的相关关系属性进行访问。

import sqlalchemy as sa

user_book_m2m = db.Table(
    "user_book",
    sa.Column("user_id", sa.ForeignKey(User.id), primary_key=True),
    sa.Column("book_id", sa.ForeignKey(Book.id), primary_key=True),
)

反映表

如果您连接到已存在表的数据库,SQLAlchemy 可以检测该模式并自动创建带有列的表。这称为反映。这些表还可以分配给模型类,其__table__属性,而不是定义完整模型。

调用扩展上的reflect()方法。它将反映每个绑定键的所有表。每个元数据的tables属性都将包含检测到的表对象。有关绑定键的更多详细信息,请参阅使用绑定实现多数据库

with app.app_context():
    db.reflect()

# From the default bind key
class Book(db.Model):
    __table__ = db.metadata.tables["book"]

# From an "auth" bind key
class User(db.Model):
    __table__ = db.metadatas["auth"].tables["user"]

在大多数情况下,自己定义模型类将更容易维护。即使您连接到更广泛的模式,也只需定义您实际将使用的模型和列。IDE 将知道可用的属性,并且像 Alembic 这样的迁移工具可以检测更改并生成模式迁移。