SQLAlchemy,如何将混合表达式设置为 'understand' 日期时间?
SQLAlchemy, how to set hybrid expression to 'understand' datetime?
我正在尝试为具有 DateTime
字段的 Person
的声明映射 class 设置 SQLAlchemy 混合体 属性称为 birth_date
代表此人的出生日期。
我想设置一个 @hybrid_property
来表示这个人的年龄,如下所示:
class Person(Base):
__tablename__ = 'person'
name: str = Column(String)
date_of_birth: DateTime = Column(DateTime)
#works fine after the objects are loaded
@hybrid_property
def age(self):
today = date.today()
if self.date_of_birth:
return today.year - self.date_of_birth.year - (
(today.month, today.day) < (self.date_of_birth.month, self.date_of_birth.day))
@age.expression
def age(cls): #Don't know how to set this up
pass
我在为混合 属性 设置 expression
时遇到问题。据我所知,表达式应该 return 一个 SQL 语句,这将有助于过滤/查询数据库中的 preson 年龄。
为此,以下 SQL 有效
SELECT (strftime('%Y', 'now') - strftime('%Y', person.date_of_birth)) - (strftime('%m-%d', 'now') < strftime('%m-%d', person.date_of_birth)) as age from person
但我不知道如何 'tell' 表达式来使用这个 SQL (或者即使这是正确的方法。)我尝试使用 text 像这样:
@age.expression
def age(cls):
current_time = datetime.utcnow()
return text(f"{current_time.year} - strftime('%Y', '{cls.date_of_birth}')")
但是没有用。我不知道如何告诉表达式将 SQL 语句用作虚拟列的 select。 (那将是年龄栏)
目标是能够像这样在 age
属性 上进行过滤和查询:
session.query(Person).filter(Person.age > 25)
请提供帮助。
混合 属性 的那部分需要 return 一个可执行的 SQLAlchemy 子句。由于 Postgres 已经有一个合适的函数,你可以直接使用它:
import sqlalchemy as sa
@age.expression
def age(cls):
return sa.func.age(cls.date_of_birth)
函数:docs,寻找age(timestamp)
。
或 MySQL:
@age.expression
def age(cls):
return sa.func.timestampdiff('year', cls.date_of_birth, sa.func.curdate())
或者在 SQLite 中:
@age.expression
def age(cls):
strftime = sa.func.strftime
year_diff = strftime('%Y', 'now') - strftime('%Y', cls.date_of_birth)
# If the month and date of the current year are before the
# month and date of birth, then we need to subtract one year
# because the "birthday" hasn't happened yet.
is_partial_year = strftime('%m-%d', 'now') < strftime('%m-%d', cls.date_of_birth)
return year_diff - is_partial_year
我正在尝试为具有 DateTime
字段的 Person
的声明映射 class 设置 SQLAlchemy 混合体 属性称为 birth_date
代表此人的出生日期。
我想设置一个 @hybrid_property
来表示这个人的年龄,如下所示:
class Person(Base):
__tablename__ = 'person'
name: str = Column(String)
date_of_birth: DateTime = Column(DateTime)
#works fine after the objects are loaded
@hybrid_property
def age(self):
today = date.today()
if self.date_of_birth:
return today.year - self.date_of_birth.year - (
(today.month, today.day) < (self.date_of_birth.month, self.date_of_birth.day))
@age.expression
def age(cls): #Don't know how to set this up
pass
我在为混合 属性 设置 expression
时遇到问题。据我所知,表达式应该 return 一个 SQL 语句,这将有助于过滤/查询数据库中的 preson 年龄。
为此,以下 SQL 有效
SELECT (strftime('%Y', 'now') - strftime('%Y', person.date_of_birth)) - (strftime('%m-%d', 'now') < strftime('%m-%d', person.date_of_birth)) as age from person
但我不知道如何 'tell' 表达式来使用这个 SQL (或者即使这是正确的方法。)我尝试使用 text 像这样:
@age.expression
def age(cls):
current_time = datetime.utcnow()
return text(f"{current_time.year} - strftime('%Y', '{cls.date_of_birth}')")
但是没有用。我不知道如何告诉表达式将 SQL 语句用作虚拟列的 select。 (那将是年龄栏)
目标是能够像这样在 age
属性 上进行过滤和查询:
session.query(Person).filter(Person.age > 25)
请提供帮助。
混合 属性 的那部分需要 return 一个可执行的 SQLAlchemy 子句。由于 Postgres 已经有一个合适的函数,你可以直接使用它:
import sqlalchemy as sa
@age.expression
def age(cls):
return sa.func.age(cls.date_of_birth)
函数:docs,寻找age(timestamp)
。
或 MySQL:
@age.expression
def age(cls):
return sa.func.timestampdiff('year', cls.date_of_birth, sa.func.curdate())
或者在 SQLite 中:
@age.expression
def age(cls):
strftime = sa.func.strftime
year_diff = strftime('%Y', 'now') - strftime('%Y', cls.date_of_birth)
# If the month and date of the current year are before the
# month and date of birth, then we need to subtract one year
# because the "birthday" hasn't happened yet.
is_partial_year = strftime('%m-%d', 'now') < strftime('%m-%d', cls.date_of_birth)
return year_diff - is_partial_year