SQLAlchemy hybrid_property和表达式

时间:2013-11-13 22:03:46

标签: python sqlalchemy

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

(简化)案例看起来像这样......

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)...

def convert_from_outside_date(in_str):
    out_date = None

    if in_str != None:
        try:
            out_date = datetime.datetime.strptime(in_str,"%Y-%m-%d")
        except ValueError:
            out_date = False
    return out_date

当我使用Contact实例时,contact.real_status_date正常用作日期时间。问题是在查询过滤器中使用Contact.real_status_date时。

db_session.query(Contact).filter(
    Contact.real_status_date > datetime.datetime.now())

使用

获取“TypeError:此子句的布尔值未定义”异常
in_str != None

转换函数的行作为堆栈跟踪的最后一部分。

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

将一个setter添加到Contact类可以工作,但添加新列似乎不应该是必要的,并且稍后会使一些表元数据解析变得更加困难,如果可以的话我想避免使用它。

_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装饰器,我是否必须实现更兼容sql的strptime函数?那会是什么样的?转换功能是否有问题导致此处出现问题?

1 个答案:

答案 0 :(得分:0)

zzzeek所述,您可以在课程中添加以下内容

根据您的数据库,它可能已经解释了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)