Python SQLAlchemy hybrid_属性和表达式

Python SQLAlchemy hybrid_属性和表达式,python,sqlalchemy,Python,Sqlalchemy,我正在使用sqlalchemy将外部进程生成的一些数据存储在postgres数据库中。外部数据有几个日期存储为字符串,我想将它们用作比较和持续时间计算的datetime对象,我希望在数据模型中进行转换以保持一致性。我试图使用hybrid_属性,但由于SQLAlchemy将hybrid_属性用作实例或类的不同方式,我遇到了问题 一个(简化的)案例看起来像这样 class Contact(Base): id = Column(String(100), primary_key=True)

我正在使用sqlalchemy将外部进程生成的一些数据存储在postgres数据库中。外部数据有几个日期存储为字符串,我想将它们用作比较和持续时间计算的datetime对象,我希望在数据模型中进行转换以保持一致性。我试图使用hybrid_属性,但由于SQLAlchemy将hybrid_属性用作实例或类的不同方式,我遇到了问题

一个(简化的)案例看起来像这样

class Contact(Base):
    id = Column(String(100), primary_key=True)
    status_date = Column(String(100))

    @hybrid_property
    def real_status_date(self):
        return convert_from_outside_date(self.status_date)
使用类似这样的转换函数(函数可以返回日期、转换失败时返回False或传递时返回None无)

当我使用Contact的实例时,Contact.real\u status\u date可以作为datetime正常工作。问题是在查询筛选器中使用Contact.real\u status\u date时

db_session.query(Contact).filter(
    Contact.real_status_date > datetime.datetime.now())
获取一个“TypeError:this子句的布尔值未定义”异常,带有

in_str != None
转换函数的行作为堆栈跟踪的最后一部分

一些答案()显示了setter函数的使用以及数据模型中新列的添加。其他答案()显示添加了@property.expression函数,该函数返回sqlalchemy可以解释为sql表达式的内容

向Contact类添加setter是可行的,但是添加新列似乎不必要,这会使一些表元数据解析在以后变得更加困难,如果可以的话,我希望避免这种情况

_real_status_date = Column(DateTime())

@hybrid_property
def real_status_date(self):
    return self._real_status_date

@real_status_date.setter
def value(self):
    self._real_status_date = convert_from_outside_date(self.status_date)
如果我使用@.expression decorator,我是否必须实现一个更兼容sql的strTime函数?那会是什么样子?转换函数有什么问题导致这里出现问题吗?

如前所述,您可以向类中添加以下内容

根据数据库的不同,它可能已经解释了python
datetime
对象

因此,它只能将转换函数修改为:

def convert_from_outside_date(in_str):
if in_str:
    try:
        return datetime.datetime.strptime(in_str,"%Y-%m-%d")
# Return None for a Null date
return None
否则,需要添加表达式函数:

@real_status_date.expression
def real_status_date(self):
    return sqlalchemy.Date(self.real_status_date)

基本上是的,如果您使用@.expression,这意味着您正在编写一个完全由数据库计算的表达式(例如聚合)。然而,这个用例对我来说意义不大——您打算如何在表达式级别使用这个属性?因为它可以返回日期值或
False
,这意味着它没有固定的类型。我不确定如何在SQL中干净地使用这样的表达式,因为您应该使用转换为单个类型的表达式。将联系人实例与我有实际日期时间的其他数据进行比较。类似于
if contact.real\u status\u date>datetime.datetime.now()
2。在联系人表的查询中筛选出特定
s的日期。查询(联系人)。筛选(Contact.real\u status\u date>last\u week
。hybrid属性旨在保留日期的原始字符串形式,以保持与最初输入db的数据的原始来源系统的兼容性。确定。因此,如果SQL版本始终返回日期或空值,那么这里的SQL版本是可以的,对吗?基本上是您拥有的主要内容要计算的是数据库端的字符串->日期,这取决于您使用的数据库类型(postgres、mysql、oracle等上的不同功能),它们都有实现这一点的功能。我知道,谢谢,当我有答案时,将详细更新-现在只使用两个单独的列,而不使用hybrid_属性
@real_status_date.expression
def real_status_date(self):
    return sqlalchemy.Date(self.real_status_date)