SQLAlchemy SQLite日期偏移过滤失效及多方言适配问题求助
问题:SQLite中SQLAlchemy混合属性日期查询失效及多数据库适配方案
问题背景
我需要编写查询,筛选出所有满足「记录日期大于今日减去days_before_activation值」条件的数据。为此用@hybrid_property定义了start属性,计算逻辑为今日日期 - days_before_activation天。但在SQLite环境下,filter查询中使用timedelta会触发错误:
E TypeError: unsupported type for timedelta days component:
InstrumentedAttribute
于是我给start属性添加了@start.expression装饰器,试图用原生SQL处理日期偏移。但当表达式中引用cls.days_before_activation时,查询结果始终为None;硬编码一个整数值却能正常运行,显然是引用该属性的方式有误。
不生效的表达式代码
@start.expression def start(cls): return func.date(datetime.today(), f'+{cls.days_before_activation} days')
生效的硬编码示例
@start.expression def start(cls): return func.date(datetime.today(), '+ 10 days')
相关完整代码
class DefPayoutOffer(db.Model): __tablename__ = 'def_payout_option_offer' id = db.Column(db.Integer, primary_key=True) visual_text = db.Column(db.String(1000), unique=False, nullable=False) days_before_activation = db.Column(db.Integer, nullable=True) @hybrid_property def start(self): return datetime.today() - timedelta(days=self.days_before_activation) @start.expression def start(cls): return func.date(datetime.today(), f'+{cls.days_before_activation} days') # 查询语句 DefPayoutOffer.query.filter(DefPayoutOffer.start > created_date).all()
多数据库适配解决方案
解决基础问题后,面临适配不同数据库方言的需求,因此放弃列表达式方案,改用expression.FunctionElement实现方言专属逻辑:
class StartCheck(expression.FunctionElement): name = 'start_check' inherit_cache = True @compiles(StartCheck, 'otherDialect') def compile(element, compiler, **kw): return "foo" @compiles(StartCheck, 'sqlite') def compile(element, compiler, **kw): return compiler.process(func.date('now', '+' + expression.cast(list(element.clauses)[0], Unicode) + ' days')) # 适配后的查询语句 DefPayoutOffer.query.filter(StartCheck(DefPayoutOffer.days_before_activation) >= date.today()).first()
内容的提问来源于stack exchange,提问作者shalama
相关产品推荐
相关产品推荐

