跟踪月末删除特定资源行的最佳方法是什么?
What is the best way to keep track of month ends for deleting rows for a specific resource?
我正在使用 Flask、Flask-Restful 和 Flask-sqlAlchemy 进行简单的休息 api,其中我有一个用户资源和一个项目资源。用户资源是项目资源的父资源。
也就是
获取https://example.com/users/1/items
获取所有物品资源
我想在每个月后自动删除所有项目。问题是如何跟踪月末?
我做了一些研究并找到了 python 日期时间和日历库。
下面的代码是我如何获得用户注册当天的月底,然后我可以计算一年中月份的其余开始和结束日期并将其保存在数据库中。但是现在我必须每次都检查 datetime.datetime.today() 然后检查开始和结束日期并删除特定用户下的项目资源。每次检查 datetime.datetime.today() 是否有效,如果等于结束日期则删除所有项目资源?
这是我计算开始和结束日期的方法
import datetime
import calendar
today = datetime.datetime.today()
days_in_current_month = calendar.monthrange(today.year, today.month)[1]
days_till_this_month_end = days_in_current_month -today.day
start_date = today + datetime.timedelta(days = days_till_this_month_end +1)
end_date = start_date
while some_condition:
# details of the condision
days_in_current_month = calendar.monthrange(end_date.year, end_date.month)[1]
end_date = end_date + datetime.timedelta(days = days_till_this_month_end +1)
这是我的用户模型:
class UserModel(db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key = True)
firstname = db.Column(db.String(80))
lastname = db.Column(db.String(80))
email = db.Column(db.String(255))
password = db.Column(db.String())
items = db.relationship('ItemModel', lazy = "dynamic")
这是我的 ItemModel:
class ItemModel(db.Model):
__tablename__ = "categories"
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(255))
date = db.Column(db.DateTime, default=datetime.utcnow)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
user = db.relationship('UserModel')
最后要删除我可以执行以下操作的项目:
@staticmethod
def delete_from_db():
ItemModel.query.filter(start_date <= end_date).delete()
db.session.commit()
您的 ItemModel
查询过滤器没有指定任何列; start_date <= end_date
表达式始终是 True
(因为 end_date
值总是比 start_date
晚)。你也把事情复杂化了。
您所要做的就是删除当月开始之前的所有行。数据库将从那里获取它。本月的开始由以下简单确定:
import datetime
today = datetime.date.today()
month_start = today.replace(day=1) # set day of the month to 1
ItemModel.query.filter(ItemModel.date < month_start).delete()
运行 每个查询都足够便宜,特别是如果 ItemModel.date
列被索引。
如果您的目标是特定数据库,那么您还可以使用该数据库的日期函数。例如,Postgresql 有一个方便的 date_trunc()
function 可用于指定要删除的行:
ItemModel.query.filter(
ItemModel.date < func.date_trunc('month', func.current_date())
).delete()
这使用 PostgreSQL CURRENT_DATE
value,t运行 将其归类到当前月份(将日期的日期设置为 1),然后删除当前月份之前的所有行。
如果您觉得这些删除查询对每个请求 运行 来说成本太高,请考虑创建 items
table 的 table view,并使用该视图在你的 SQLAlchemy 模型中。然后视图查询仅显示当月的项目:
CREATE OR REPLACE current_items WITH
SELECT * FROM items
WHERE items.date >= date_trunc(CURRENT_DATE, 'month')
并使用 current_items
作为 table 名称来支持您的 ItemModel
对象,并使用单独的批处理删除项目 table 中较旧的任何行, 以保持数据库清洁。这样,您的 SQLAlchemy 查询只能看到当月的项目,并且每次批处理处理删除这些行时都会执行一次删除。
除了视图,您还可以让 SQLAlchemy 通过事件挂钩自动应用过滤器。这是一个 filtered query implementation:
@event.listens_for(Query, "before_compile", retval=True)
def before_itemmodel_compile(query):
"""Limit all ItemModel queries to the current month"""
if query._execution_options.get("include_all", False):
return query
for ent in query.column_descriptions:
entity = ent['entity']
if entity is None:
continue
insp = inspect(ent['entity'])
mapper = getattr(insp, 'mapper', None)
if mapper and mapper.class_ is ItemModel:
today = datetime.date.today()
month_start = today.replace(day=1) # set day of the month to 1
query = query.enable_assertions(False).filter(
ent['entity'].date >= month_start)
return query
我正在使用 Flask、Flask-Restful 和 Flask-sqlAlchemy 进行简单的休息 api,其中我有一个用户资源和一个项目资源。用户资源是项目资源的父资源。
也就是
获取https://example.com/users/1/items 获取所有物品资源
我想在每个月后自动删除所有项目。问题是如何跟踪月末?
我做了一些研究并找到了 python 日期时间和日历库。
下面的代码是我如何获得用户注册当天的月底,然后我可以计算一年中月份的其余开始和结束日期并将其保存在数据库中。但是现在我必须每次都检查 datetime.datetime.today() 然后检查开始和结束日期并删除特定用户下的项目资源。每次检查 datetime.datetime.today() 是否有效,如果等于结束日期则删除所有项目资源?
这是我计算开始和结束日期的方法
import datetime
import calendar
today = datetime.datetime.today()
days_in_current_month = calendar.monthrange(today.year, today.month)[1]
days_till_this_month_end = days_in_current_month -today.day
start_date = today + datetime.timedelta(days = days_till_this_month_end +1)
end_date = start_date
while some_condition:
# details of the condision
days_in_current_month = calendar.monthrange(end_date.year, end_date.month)[1]
end_date = end_date + datetime.timedelta(days = days_till_this_month_end +1)
这是我的用户模型:
class UserModel(db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key = True)
firstname = db.Column(db.String(80))
lastname = db.Column(db.String(80))
email = db.Column(db.String(255))
password = db.Column(db.String())
items = db.relationship('ItemModel', lazy = "dynamic")
这是我的 ItemModel:
class ItemModel(db.Model):
__tablename__ = "categories"
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(255))
date = db.Column(db.DateTime, default=datetime.utcnow)
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
user = db.relationship('UserModel')
最后要删除我可以执行以下操作的项目:
@staticmethod
def delete_from_db():
ItemModel.query.filter(start_date <= end_date).delete()
db.session.commit()
您的 ItemModel
查询过滤器没有指定任何列; start_date <= end_date
表达式始终是 True
(因为 end_date
值总是比 start_date
晚)。你也把事情复杂化了。
您所要做的就是删除当月开始之前的所有行。数据库将从那里获取它。本月的开始由以下简单确定:
import datetime
today = datetime.date.today()
month_start = today.replace(day=1) # set day of the month to 1
ItemModel.query.filter(ItemModel.date < month_start).delete()
运行 每个查询都足够便宜,特别是如果 ItemModel.date
列被索引。
如果您的目标是特定数据库,那么您还可以使用该数据库的日期函数。例如,Postgresql 有一个方便的 date_trunc()
function 可用于指定要删除的行:
ItemModel.query.filter(
ItemModel.date < func.date_trunc('month', func.current_date())
).delete()
这使用 PostgreSQL CURRENT_DATE
value,t运行 将其归类到当前月份(将日期的日期设置为 1),然后删除当前月份之前的所有行。
如果您觉得这些删除查询对每个请求 运行 来说成本太高,请考虑创建 items
table 的 table view,并使用该视图在你的 SQLAlchemy 模型中。然后视图查询仅显示当月的项目:
CREATE OR REPLACE current_items WITH
SELECT * FROM items
WHERE items.date >= date_trunc(CURRENT_DATE, 'month')
并使用 current_items
作为 table 名称来支持您的 ItemModel
对象,并使用单独的批处理删除项目 table 中较旧的任何行, 以保持数据库清洁。这样,您的 SQLAlchemy 查询只能看到当月的项目,并且每次批处理处理删除这些行时都会执行一次删除。
除了视图,您还可以让 SQLAlchemy 通过事件挂钩自动应用过滤器。这是一个 filtered query implementation:
@event.listens_for(Query, "before_compile", retval=True)
def before_itemmodel_compile(query):
"""Limit all ItemModel queries to the current month"""
if query._execution_options.get("include_all", False):
return query
for ent in query.column_descriptions:
entity = ent['entity']
if entity is None:
continue
insp = inspect(ent['entity'])
mapper = getattr(insp, 'mapper', None)
if mapper and mapper.class_ is ItemModel:
today = datetime.date.today()
month_start = today.replace(day=1) # set day of the month to 1
query = query.enable_assertions(False).filter(
ent['entity'].date >= month_start)
return query