SQLAlchemy添加混合属性:datetime与数值字段求和查询报错求助
问题描述
我想在SQLAlchemy模型中计算一个结合两个现有字段的属性,并将其用于查询参数。模型定义如下:
class Booking(BaseORMModel): start: Mapped[datetime] = mapped_column(TIMESTAMP(timezone=True)) duration_minutes: Mapped[int] = mapped_column(Numeric)
我需要动态计算ended_at字段,其值为start与duration_minutes对应的时长之和。我的实现尝试如下:
class Booking(BaseORMModel): ... @hybrid_property def ended_at(self): return self.start + timedelta(minutes=self.duration_minutes) @ended_at.expression def ended_at(cls): duration_interval = func.cast(concat(cls.duration_minutes, ' MINUTES'), INTERVAL) ended_at = func.sum(cls.start + duration_interval) return ended_at
查询语句:
query = query.where(Booking.ended_at < now)
执行时出现如下错误:
sqlalchemy.exc.ProgrammingError: (psycopg.errors.UndefinedFunction) function sum(timestamp with time zone) does not exist
解决方案
错误根源是误用了func.sum()——这个函数用于多行数据的聚合求和,而此处仅需为每行记录的start时间加上对应分钟间隔,完全不需要聚合操作,直接返回时间相加的表达式即可。
修正后的完整模型实现:
from datetime import timedelta from sqlalchemy import func, cast, Interval, TIMESTAMP from sqlalchemy.orm import Mapped, mapped_column from your_base_model import BaseORMModel # 替换为实际的基类导入 class Booking(BaseORMModel): start: Mapped[datetime] = mapped_column(TIMESTAMP(timezone=True)) duration_minutes: Mapped[int] = mapped_column(Numeric) @hybrid_property def ended_at(self): return self.start + timedelta(minutes=self.duration_minutes) @ended_at.expression def ended_at(cls): # 将数值类型的duration_minutes转为分钟间隔,与start时间相加 return cls.start + cast(cls.duration_minutes, Interval(minutes=True))
针对PostgreSQL,还可以用更贴合数据库原生特性的写法:
@ended_at.expression def ended_at(cls): # 利用PostgreSQL的make_interval函数直接生成分钟间隔 return cls.start + func.make_interval(minutes=cls.duration_minutes)
修正后执行原查询语句,即可正常筛选出ended_at小于指定时间的记录。
内容的提问来源于stack exchange,提问作者Christian
相关产品推荐
相关产品推荐

