写一个 Model 类,数据库里到底会生成什么?default 与 server_default 有什么不同?没写主键会怎样?已有的表怎么映射?这篇用真实的 PostgreSQL 逐项对照 SQLAlchemy 生成的 DDL 与数据库里实际的结构。
{'UserProfile': 'user_profile', 'HTTPRequestLog': 'http_request_log', 'Custom': 'my_custom'}没有主键的模型 → ArgumentError: Mapper Mapper[NoPk(nopk)] could not assemble any primary key columns for mapped table 'nopk'
SQLAlchemy 生成的 CREATE TABLE:
CREATE TABLE product (
id SERIAL NOT NULL,
name VARCHAR(30) NOT NULL,
note TEXT,
price NUMERIC(8, 2),
active BOOLEAN DEFAULT true,
created TIMESTAMP WITHOUT TIME ZONE DEFAULT now(),
meta JSON,
kind kind,
stock INTEGER NOT NULL CHECK (stock >= 0),
PRIMARY KEY (id),
UNIQUE (name)
)
PG 里实际的列:
id integer null=NO default=nextval('product_id_seq'::regclass)
name character varying null=NO default=-
note text null=YES default=-
price numeric null=YES default=-
active boolean null=YES default=true
created timestamp without time zone null=YES default=now()
meta json null=YES default=-
kind USER-DEFINED null=YES default=-
stock integer null=NO default=-
PG 里的索引: ix_product_name_active, product_name_key, product_pkeyORM 发出的 INSERT(只显示列名部分): INSERT INTO product (name, note, price, active, created, kind, stock) VALUES (…) 结果行: p1|0.00|t|t|0 raw||t|t|1 直接用 SQL 插入(绕过 ORM)时,只有 server_default 起作用: raw||t|t|1
stock=-1(CheckConstraint) → IntegrityError / 底层 CheckViolation 重名 p1(unique) → IntegrityError / 底层 UniqueViolation
CREATE TABLE acct ( id SERIAL NOT NULL, name VARCHAR(30) NOT NULL, nick VARCHAR, age INTEGER NOT NULL, PRIMARY KEY (id) )
Product.name 的类型: InstrumentedAttribute | Product.__table__.name: product | 列: ['id', 'name', 'note', 'price', 'active'] ... mapper 的映射属性数: 9 | 主键: ['id'] 实例的 p.name: tmp | 没赋值的 p.note: None | 没赋值的 p.price(default 还没生效): None
反射出的表 legacy 的列: [('id', 'INTEGER', False), ('title', 'TEXT', False), ('score', 'INTEGER', True)]
db.reflect() 是不是也把 product 反射进来: True