如何让SQLAlchemy知晓必填字段由数据库端触发器填充?
核心配置思路:标记字段为数据库端生成,禁止ORM插入时包含
只使用FetchedValue()不足以让ORM跳过字段校验,必须同时配置insertable=False(针对插入时生成的字段)或updateable=False(针对更新时触发的字段),明确告诉ORM:该字段由数据库触发器负责生成,不需要在INSERT/UPDATE语句中包含。
基础场景示例
以你的People模型为例,修改列定义如下:
from sqlalchemy import Column, DateTime, String from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.sql import FetchedValue Base = declarative_base() class People(Base): __tablename__ = 'people' id = Column(String, primary_key=True) name = Column(String) # 关键配置:insertable=False让ORM插入时忽略该字段,FetchedValue()支持插入后自动获取值 date_added = Column(DateTime, default=FetchedValue(), insertable=False)
此时直接创建People实例插入,无需传入date_added参数,ORM会自动跳过该字段,由数据库触发器生成值;如果需要获取生成的date_added,插入后直接访问实例的该属性即可(SQLAlchemy会自动执行查询获取)。
复杂场景(继承、关联关系)的适配
涉及继承或关联的模型,需确保所有层级的自动生成字段都正确配置insertable=False,避免ORM生成语句时错误包含这些字段。
继承场景示例(Manager继承Employee)
假设父类Employee有触发器生成的create_time字段:
class Employee(Base): __tablename__ = 'employees' id = Column(Integer, primary_key=True) name = Column(String) create_time = Column(DateTime, default=FetchedValue(), insertable=False) type = Column(String) __mapper_args__ = { 'polymorphic_on': type, 'polymorphic_identity': 'employee' } class Manager(Employee): __tablename__ = 'managers' id = Column(Integer, ForeignKey('employees.id'), primary_key=True) department = Column(String) __mapper_args__ = { 'polymorphic_identity': 'manager' }
父类的create_time已配置insertable=False,子类Manager继承后,插入实例时ORM不会在语句中包含该字段,避免触发错误。
关联关系场景示例(Manager关联Company)
关联模型中的自动生成字段同样需配置insertable=False:
class Company(Base): __tablename__ = 'companies' id = Column(Integer, primary_key=True) name = Column(String) create_time = Column(DateTime, default=FetchedValue(), insertable=False) class Manager(Employee): __tablename__ = 'managers' id = Column(Integer, ForeignKey('employees.id'), primary_key=True) department = Column(String) company_id = Column(Integer, ForeignKey('companies.id')) company = relationship("Company") __mapper_args__ = { 'polymorphic_identity': 'manager' }
插入Manager时,只需传入name、department、company_id(或关联的company实例),无需处理create_time字段,ORM会自动跳过,由数据库触发器生成值。
额外说明:是否需要插入后获取生成值
如果不需要插入后立即获取生成的字段值,可以去掉default=FetchedValue(),只保留insertable=False,这样ORM不会主动执行额外查询,但实例的该属性会是None,直到你重新查询该实例。
内容的提问来源于stack exchange,提问作者Logos Masters

