Как запустить задачу Django на определенную дату в поле модели
У меня есть модель, содержащая следующее поле
class EventConfig(models.Model):
end_date = models.DateTimeField(blank=True, null=True)
У меня установлен celery, который периодически отправляет электронные письма и запускает другие задачи через заданные временные интервалы, например, каждый час или в 12 часов дня. Однако если я хочу, чтобы письмо отправлялось точно по достижении 'end_date', как лучше всего это сделать? Я понимаю, что могу установить расписание Celery на выполнение каждую минуту для проверки даты, но является ли запуск пакетного задания каждые 60 секунд на постоянной основе лучшим подходом или у этого есть недостатки?
Есть ли способ, например, настроить расписание crontab на чтение из списка значений, чтобы я мог сделать что-то вроде schedule_list = EventConfig.objects.all(). values_list(end_date, flat=True) или schedule_list.append(self.end_date) всякий раз, когда сохраняется экземпляр модели, и заставить Celery читать из «schedule_list», чтобы пакетные задания срабатывали только в нужное время?
Или есть лучший способ сделать это с сельдереем или без него?
Вы можете проверить, больше ли текущая дата, чем дата окончания, используя @property на модели
@property
def is_expired(self):
return date.today() > self.end_date
Тогда вы можете просто проверить с помощью if obj.is_expired
Я думаю, что вы можете использовать Celery Beat для динамического планирования задач. Создайте пользовательский планировщик, который считывает дату окончания_даты из вашей модели EventConfig и планирует задачу соответствующим образом.
from celery import shared_task from celery.schedules import crontab from celery.beat import Scheduler
class DynamicScheduler(Scheduler): def init(self, *args, **kwargs): super().init(*args, **kwargs) self.schedule = self.get_schedule()
def get_schedule(self):
schedule = {}
for config in EventConfig.objects.all():
schedule[config.id] = {
'task': 'your_task_name',
'schedule': config.end_date,
'args': (config.id,)
}
return schedule
app.conf.beat_scheduler = 'path.to.DynamicScheduler'