Ваш фильтр запросов 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()
функцию , которую можно использовать для указания, какие строки отбрасывать:
ItemModel.query.filter(
ItemModel.date < func.date_trunc('month', func.current_date())
).delete()
При этом используется значение PostgreSQL CURRENT_DATE
, усекает его до текущего месяца (который устанавливает день даты равным 1), затем удаляет все строки, предшествующие текущему месяцу.
Если вы считаете, что эти запросы на удаление слишком дороги для выполненияПри каждом отдельном запросе рассмотрите возможность создания табличного представления таблицы items
и используйте это представление в своей модели SQLAlchemy.В запросе на просмотр отображаются только элементы текущего месяца:
CREATE OR REPLACE current_items WITH
SELECT * FROM items
WHERE items.date >= date_trunc(CURRENT_DATE, 'month')
и использование current_items
в качестве имени таблицы для поддержки объектов ItemModel
, а отдельный пакетный процесс удаляет все строки из элементовтаблица, которая старше, чтобы сохранить базу данных в чистоте.Таким образом, ваши запросы SQLAlchemy только когда-либо смогут увидеть элементы текущего месяца, и удаление будет выполняться один раз, пока пакетный процесс завершает удаление этих строк.
Вместо представления можно также применить SQLAlchemy.фильтр автоматически, через перехват событий.Это реализация фильтра с фильтром :
@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