SQLAlchemy有效地将以Python表示的查询转换为SQL。但这是基于
Column定义模型时分配给数据类型的相对肤浅的。
这意味着它不一定会
datetime.datetime在其
DateTime构造上复制Python的API-
毕竟,这两个类的作用是完全不同的!(
datetime.datetime为Python提供了日期时间功能,而SQLAlchemy
DateTime告诉其SQL转换逻辑它正在处理SQL
DATETIME或TIMESTAMP列)。
但是不用担心!您可以通过多种方法来实现自己的目标,其中一些方法非常简单。我认为最简单的三个是:
- 使用完整的
datetime
实例而不是其组成部分(天,月,年)构造过滤器。 extract
在过滤器中使用SQLAlchemy的构造。- 在模型中定义三个混合属性,这些属性返回可以进行过滤的付款月份,日期和年份。
datetime对象
这是实现所要尝试的三种(简便)方法中最简单的方法,并且执行速度也最快。基本上,不要尝试对查询中的每个组件(日,月,年)分别进行过滤,而只需使用一个
datetime值即可。
基本上,以下内容应与您在上面的查询中尝试执行的 *** 作等效:
from datetime import datetimetodays_datetime = datetime(datetime.today().year, datetime.today().month, datetime.today().day)payments = Payment.query.filter(Payment.due_date >= todays_datetime).all()
现在,
payments应该是到期日在系统当前日期的开始(时间00:00:00)之后的所有付款。
如果您想变得更复杂,例如最近30天进行的过滤付款。您可以使用以下代码进行 *** 作:
from datetime import datetime, timedeltafilter_after = datetime.today() - timedelta(days = 30)payments = Payment.query.filter(Payment.due_date >= filter_after).all()
您可以使用
and_和组合多个过滤器目标
or_。例如,要回支付那名在过去30天骨 及 多是因为15年前,你可以使用:
from datetime import datetime, timedeltafrom sqlalchemy import and_thirty_days_ago = datetime.today() - timedelta(days = 30)fifteen_days_ago = datetime.today() - timedelta(days = 15)# Using and_ IMPLICITLY:payments = Payment.query.filter(Payment.due_date >= thirty_days_ago, Payment.due_date <= fifteen_days_ago).all()# Using and_ explicitly:payments = Payment.query.filter(and_(Payment.due_date >= thirty_days_ago, Payment.due_date <= fifteen_days_ago)).all()
从您的角度来看,这里的技巧是
datetime在执行查询之前正确构造过滤器目标实例。使用
extract构造
SQLAlchemy的
extract表达式(在此处记录)用于执行SQL
EXTRACT语句,这是在SQL中可以从DATETIME
/ TIMESTAMP值中提取月,日或年的方式。
使用这种方法,SQLAlchemy告诉您的SQL数据库“首先,从我的DATETIME列中提取月份,日期和年份, 然后 对提取的值 进行
过滤”。请注意,这种方法 将比
datetime如上所述对值进行过滤慢。但这是这样的:
使用混合属性from sqlalchemy import extractpayments = Payment.query.filter(extract('month', Payment.due_date) >= datetime.today().month, extract('year', Payment.due_date) >= datetime.today().year, extract('day', Payment.due_date) >= datetime.today().day).all()
SQLAlchemy混合属性是很棒的事情。它们使您可以透明地应用Python功能,而无需修改数据库。我怀疑在这种特定的用例中,它们可能会过大,但是它们是实现所需目标的第三种方法。
基本上,您可以将混合属性视为实际上不在数据库中存在的“虚拟列”,但是哪些SQLAlchemy可以在需要时从数据库列中进行即时计算。
在您的具体问题,我们定义了三种混合属性:
due_date_day,
due_date_month,
due_date_year在你的
Payment模型。这是如何工作的:
... your existing import statementsfrom sqlalchemy import extractfrom sqlalchemy.ext.hybrid import hybrid_propertyclass Payment(db.Model, UserMixin): id = db.Column(db.Integer, unique = True, primary_key = True) payment_to = db.Column(db.String, nullable = False) amount = db.Column(db.Float, nullable = False) due_date = db.Column(db.DateTime, nullable = False, default = datetime.strftime(datetime.today(), "%b %d %Y")) week_of = db.Column(db.String, nullable = False) @hybrid_property def due_date_year(self): return self.due_date.year @due_date_year.expression def due_date_year(cls): return extract('year', cls.due_date) @hybrid_property def due_date_month(self): return self.due_date.month @due_date_month.expression def due_date_month(cls): return extract('month', cls.due_date) @hybrid_property def due_date_day(self): return self.due_date.day @due_date_day.expression def due_date_day(cls): return extract('day', cls.due_date)payments = Payment.query.filter(Payment.due_date_year >= datetime.today().year, Payment.due_date_month >= datetime.today().month, Payment.due_date_day >= datetime.today().day).all()
这是上面的 *** 作:
- 您已经在定义
Payment
模型了。 - 但你要添加一些只读实例的属性叫
due_date_year
,due_date_month
和due_date_day
。使用due_date_year
作为一个例子,这是在 *** 作的实例属性 实例 您的Payment
类。这意味着当您执行one_of_my_payments.due_date_year
该属性时,due_date
将从Python实例中提取值。因为这都是在Python中发生的(即不接触数据库),所以它将对datetime.datetime
SQLAlchemy已存储在您的实例中的已转换对象进行 *** 作。它将返回的结果due_date.year
。 - 然后添加一个 class 属性。这是用装饰的位
@due_date_year.expression
。这个装饰器告诉SQLAlchemy,当它将引用转换due_date_year
为SQL表达式时,它应该按照此方法中的定义进行 *** 作。因此,上面的示例告诉SQLAlchemy“如果您需要due_date_year
在SQL表达式中使用,那么应该extract('year', Payment.due_date)
如何due_date_year
表达。
(注意:上面的示例假定
due_date_year,
due_date_month和
due_date_day均为只读属性。您当然也可以使用
@due_date_year.setter也接受参数的
(self,value)方法来定义自定义设置器)结论
在这三种方法中,我认为第一种方法(对进行过滤
datetime)既最容易理解,也最容易实现,并且执行速度最快。这可能是最好的方法。但是这三种方法的原理非常重要,我认为这将帮助您从SQLAlchemy中获得最大价值。希望这对您有所帮助!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)