我正在使用 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 时返回 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 表达式的内容。
向 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 装饰器,我是否必须实现一个更兼容 sql 的 strptime 函数?那会是什么样子?在这里造成麻烦的转换功能有问题吗?