SQLAlchemy-用DateTime列查询以按月日年过滤

SQLAlchemy-用DateTime列查询以按月日年过滤,第1张

SQLAlchemy-用DateTime列查询以按月/日/年过滤

SQLAlchemy有效地将以Python表示的查询转换为SQL。但这是基于

Column
定义模型时分配给数据类型的相对肤浅的。

这意味着它不一定会

datetime.datetime
在其
DateTime
构造上复制Python的API-
毕竟,这两个类的作用是完全不同的!(
datetime.datetime
为Python提供了日期时间功能,而SQLAlchemy
DateTime
告诉其SQL转换逻辑它正在处理SQL
DATETIME或TIMESTAMP列)。

但是不用担心!您可以通过多种方法来实现自己的目标,其中一些方法非常简单。我认为最简单的三个是:

  1. 使用完整的
    datetime
    实例而不是其组成部分(天,月,年)构造过滤器。
  2. extract
    在过滤器中使用SQLAlchemy的构造。
  3. 在模型中定义三个混合属性,这些属性返回可以进行过滤的付款月份,日期和年份。
过滤
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()

这是上面的 *** 作:

  1. 您已经在定义
    Payment
    模型了。
  2. 但你要添加一些只读实例的属性叫
    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
  3. 然后添加一个 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中获得最大价值。希望这对您有所帮助!



欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5662168.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-16

发表评论

登录后才能评论

评论列表(0条)

保存