这是我的模型:
class Base(DeclarativeBase):
pass
class AppUser(Base):
__tablename__ = "app_user"
id: Mapped[int] = mapped_column(Integer, primary_key=True, index=True)
created_at: Mapped[DateTime] = mapped_column(DateTime, default=func.now())
updated_at: Mapped[DateTime] = mapped_column(
DateTime,
default=func.now(),
onupdate=func.now(),
)
telegram_id: Mapped[int] = mapped_column(BigInteger, unique=True, index=True)
telegram_username: Mapped[str] = mapped_column(String(60), unique=True, index=True)
language: Mapped[str] = mapped_column(String(10), default="en")
comment: Mapped[str] = mapped_column(String(255))
运行后
pdm run alembic revision --autogenerate -m "Create a baseline migrations"
我得到以下迁移脚本:
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('app_user',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=False),
sa.Column('updated_at', sa.DateTime(), nullable=False),
sa.Column('telegram_id', sa.BigInteger(), nullable=False),
sa.Column('telegram_username', sa.String(length=60), nullable=False),
sa.Column('language', sa.String(length=10), nullable=False),
sa.Column('comment', sa.String(length=255), nullable=False),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_app_user_id'), 'app_user', ['id'], unique=False)
op.create_index(op.f('ix_app_user_telegram_id'), 'app_user', ['telegram_id'], unique=True)
op.create_index(op.f('ix_app_user_telegram_username'), 'app_user', ['telegram_username'], unique=True)
# ### end Alembic commands ###
没有任何内容表明 telegram_id、telegram_hostname、语言和注释不能为空。 我在 alembic 文档中没有看到任何内容表明这是默认行为,并且由于 SQLAlchemy 默认情况下假定“nullable=True”,所以我认为 alembic 也应该......
SQLAlchemy(因此也是 alembic)的默认行为不是“nullable=True”。 它实际上源自类型注释(即Optional或“| None”表示可为空):
https://docs.sqlalchemy.org/en/20/orm/mapping_api.html#sqlalchemy.orm.mapped_column.params.nullable
nullable¶ – 可选布尔值,列是否应该为“NULL”或“NOT” 无效的”。如果省略,则可空性源自类型注释 基于是否键入。可选是否存在。可为空的默认值 对于非主键列,否则为 True,对于主键列,则为 False 关键栏目。