Ответ 1
Чтобы автоматически обновить поле модели через определенное время, вы можете использовать Задачи сельдерея.
Шаг 1. Создание задачи Сельдерея
Сначала мы создадим задачу celery c set_race_as_inactive
, которая установит флаг is_active
race_object
на False
после того, как текущая дата будет больше, чем end_time
race_object
.
Эта задача будет выполняться Celery
, только если текущее время больше, чем объект гонки end_time
.
@app.task
def set_race_as_inactive(race_object):
"""
This celery task sets the 'is_active' flag of the race object
to False in the database after the race end time has elapsed.
"""
race_object.is_active = False # set the race as not active
race_object.save() # save the race object
Шаг 2: вызовите эту задачу celery, используя eta
аргумент
После создания задачи сельдерея set_race_as_inactive
, нам нужно вызвать эту задачу сельдерея.
Мы будем называть эту задачу всякий раз, когда мы сохраняем новую race_object
в нашей базе данных. Таким образом, всякий раз, когда новый race_object
будет сохранен, будет запущена задача celery, которая будет выполняться только после end_time
race_object
.
Мы будем называть задачу с помощью apply_async()
и передавать аргумент eta
как end_time
race_object
.
ETA (расчетное время прибытия) позволяет вам установить конкретную дату и время, которое является самым ранним моментом, когда ваша задача будет выполнена.
Задача будет выполнена в течение некоторого времени после указанного дату и время, но не обязательно в это точное время.
from my_app.tasks import set_race_as_inactive
class RaceModel(models.Model):
...
def save(self, *args, **kwargs):
..
create_task = False # variable to know if celery task is to be created
if self.pk is None: # Check if instance has 'pk' attribute set
# Celery Task is to created in case of 'INSERT'
create_task = True # set the variable
super(RaceModel, self).save(*args, **kwargs) # Call the Django "real" save() method.
if create_task: # check if task is to be created
# pass the current instance as 'args' and call the task with 'eta' argument
# to execute after the race `end_time`
set_race_as_inactive.apply_async(args=[self], eta=self.end_time) # task will be executed after 'race_end_time'
Эта проверка self.pk
с помощью None
выполняется так, что только при создании новых объектов создается задача celery. Если мы этого не сделаем, то для каждого вызова .save()
(либо INSERT
или UPDATE
) будет создана задача сельдерея, которую мы не хотим. Это приведет к множеству ненужных задач сельдерея, ожидающих исполнения, и перегрузит наши очереди сельдерея.
Преимущества использования <пользы для использования сельдерея - это то, что обновление флага is_active
будет происходить автоматически в фоновом режиме асинхронно, если вам не нужно беспокоиться об их ручном обновлении. Каждый раз, когда создается новый объект гонки, задача будет запущена, и Сельдерей отложит свое исполнение до end_time
гонки. По истечении end_time
, Celery выполнит эту задачу.