使用SQLAlchemy 2.0结合dataclass时如何配置服务端默认值?
解决SQLAlchemy插入时使用数据库默认timestamp字段的问题
你的核心需求是让数据库端的ts字段(带时区的timestamp,默认值为当前时间)自动赋值,同时SQLAlchemy不在客户端传值,还要保留类型检查。之前的代码报错是因为SQLAlchemy不知道这个字段的默认值由数据库提供,所以尝试插入null触发约束错误。
正确的代码配置如下:
import datetime from sqlalchemy import DateTime, text from sqlalchemy.orm import Mapped, mapped_column from sqlalchemy.dataclasses import MappedAsDataclass from sqlalchemy.ext.declarative import DeclarativeBase class Base(MappedAsDataclass, DeclarativeBase): pass class MyTable(Base): __tablename__ = "my_table" # 必须指定对应数据库表名 ts: Mapped[datetime.datetime] = mapped_column( DateTime(timezone=True), # 对应数据库的timestamp with time zone类型 init=False, # 禁止dataclass初始化时传入该字段 nullable=False, server_default=text("CURRENT_TIMESTAMP") # 告知SQLAlchemy使用数据库默认值 )
关键配置说明:
DateTime(timezone=True):和数据库的timestamp with time zone类型严格匹配,确保类型检查生效,避免类型不兼容问题。server_default=text("CURRENT_TIMESTAMP"):告诉SQLAlchemy这个字段的默认值由数据库负责生成,插入数据时不会在SQL语句中包含ts字段,彻底交给数据库处理。init=False:保持dataclass初始化时不需要传入ts参数,符合你的使用习惯。
如果需要跨数据库兼容,可以用SQLAlchemy内置的函数替代原生SQL文本:
from sqlalchemy.sql import func # 替换server_default为: server_default=func.current_timestamp()
这样配置后,插入MyTable()(传入其他必填字段)时,SQLAlchemy生成的INSERT语句不会包含ts,数据库会自动填充当前带时区的时间,同时从数据库查询回来的ts值会被正确解析为datetime.datetime类型,满足类型检查要求。
内容的提问来源于stack exchange,提问作者lilydjwg
相关产品推荐
相关产品推荐

