模型和表¶
使用 db.Model
类定义模型,或使用 db.Table
类创建表。两者都处理 Flask-SQLAlchemy 的绑定键,以与特定引擎关联。
初始化基类¶
SQLAlchemy
2.x 为您的模型提供了多个可能的基类:DeclarativeBase 或 DeclarativeBaseNoMeta。
创建这些类的子类
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 这样的迁移工具可以检测更改并生成模式迁移。