SQLAlchemy 在原生 SQL 表达式中重写 types.DateTime

0 投票
1 回答
702 浏览
提问于 2025-04-16 03:17

在使用SQLAlchemy和原始SQL表达式时,是否可以改变默认的type.DateTime行为呢?

比如,当我使用下面这段代码:

myconnection.execute(text("select * from mytable where mydate > :mydate), {'mydate': mypythondatetimeobject)}

我希望type.DateTime能够自动去掉日期时间对象中的时区信息。

更新:我发现通过在查询中使用bindparam和Typedecorator可以做到这一点,像这样:

class MyType(types.TypeDecorator):
    impl = types.DateTime

    def process_bind_param(self, value, dialect):
        if value is not None:
            return value.replace(tzinfo=None)

session.execute(
    text(myquery, bindparams=[bindparam('mydateparam', 
                                        type_=MyType())]), 
    {'mydateparam':mydate}
)

但是我真的不想在每个查询中都使用“bindparams”。难道没有办法简单地替换或覆盖默认的types.DateTime行为吗?

1 个回答

1

如果你使用的是基于表格元数据的SQL表达式,那么你只需要在合适的列上设置你的MyType。直接用文本的方式就没那么方便了。不过,你可以把你的MyType放到sqlalchemy.types.type_map里,跟datetime类关联起来,不过现在这个方法还不是公开的API。

如果是我,我会这样做:

def mytext(stmt, params):
    bindparams = []
    for k, v in params:
        if isinstance(v, datetime):
            type_ = MyType()
        else:
            type_ = None
        bindparams.append(bindparam(k, v, type_=type))
    return text(stmt, bindparams=bindparams)

然后就可以用mytext("select * from table where date=:date", {'date':datetime.today()})来查询了。

撰写回答