Как запустить задачу 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'

Вернуться на верх