Продвинутый Django 5 для продолжающих

Прогресс по курсу:  0/193

9.4 Периодические задания
2 из 2 шагов пройдено

Давайте теперь создадим периодическую задачу. Откройте publish/celery.py и зарегистрируйте задания:

import os
from celery import Celery
from celery.schedules import crontab

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_celery.settings')
app = Celery('publish', broker_connection_retry=False,
             broker_connection_retry_on_startup=True, )
app.config_from_object('django.conf:settings')
broker_connection_retry = False

app.autodiscover_tasks()
app.conf.beat_schedule = {
    'send-report-every-single-minute': {
        'task': 'publish.tasks.send_view_count_report',
        'schedule': crontab(),
    },
}


Мы создавали расписание, которое запускает задачу publisher.tasks.send_view_count_report каждую минуту, как показано в нотации crontab().

Вы также можете указать различные расписания Celery Crontab:

Пример

Значение

crontab()

Выполняется каждую минуту.

crontab(minute=0, hour=0)

Выполняется ежедневно в полночь.

crontab(minute=0, hour='*/3')

Выполняется каждые три часа: полночь, 3 утра, 6 утра, 9 утра, полдень, 15:00, 6 вечера, 9 вечера.

crontab(minute=0,

hour='0,3,6,9,12,15,18,21')

То же, что и в прошлом.

crontab(minute='*/15')

Выполняется каждые 15 минут.

crontab(day_of_week='sunday')

Выполняется каждую минуту (!) по воскресеньям.

crontab(minute='*',

hour='*',day_of_week='sun')

То же, что и в прошлом.

crontab(minute='*/10',

hour='3,17,22',day_of_week='thu,fri')

Выполняется каждые десять минут, но только между 3–4 часами утра, 5–6 вечера и 22–23 часами по четвергам и пятницам.

crontab(minute=0,hour='*/2,*/3')

Выполняется в каждый чётный час и в каждый час делимый на три. Это означает: каждый час, кроме: 1:00, 5:00, 7:00, 11:00, 13:00, 17:00, 19:00, 23:00

crontab(minute=0, hour='*/5')

Выполняется в каждый час, делимый на 5.

crontab(minute=0,hour='*/3,8-17')

Выполняется в каждый час, делимый на 3, и каждый час в рабочее время (с 8:00 до 17:00).

crontab(0, 0,day_of_month='2')

Выполняется во второй день каждого месяца.

crontab(0, 0,

day_of_month='2-30/2')

Выполняется в каждый чётный день месяца.

crontab(0, 0,

day_of_month='1-7,15-21')

Выполняется в первую и третью недели месяца.

crontab(0, 0,day_of_month='11',

month_of_year='5')

Выполняется одиннадцатого мая каждого года.

crontab(0, 0,

month_of_year='*/3')

Выполняется каждый день в первый месяц каждого квартала.


Откроем еще одну консоль, активируйте соответствующее окружение и запустите службу Celery Beat:

celery -A publish beat


Работа службы Beat заключается в том, чтобы задавать задачи в Celery в соответствии с расписанием. Давайте оставим на несколько минут запущенную нашу задачу:


Проверим почту:


Мы видим что расписание выполняет задачу send_view_count_report каждую минуту в соответствии с настройкой. Это удобно для тестирования, но не рекомендуется для реального веб-приложения.


Задачи часто используются для выполнения ненадежных операций, операций, зависящих от внешних ресурсов, или задачи, которые могут легко падать по различным причинам. Вот инструкция, чтобы сделать их более надежными:

  • Сделать задачи идемпотентными. Идемпотентная задача - это задача, которая, не изменяет состояние системы, если она остановлена на полпути. Задача либо полностью вносит изменения в систему, либо нет.
  • Повторение задачи. Если задача падает, рекомендуется попробовать выполнять ее снова и снова, пока она не будет выполнена успешно. Вы можете сделать это с помощью Celery Retry.

  • Комментария
Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий

у меня приходят два смс каждую минуту одно такое как надо а второе 

 

Адрес не найден

Сообщение не доставлено, так как адрес admin@gmail.comне найден или не принимает входящие письма.

admin у меня не верефицирован, у вас явно ошибка в коде где то (((

Изменен No Name

@No_Name, у вас тут в коде не доработка в publish/tasks.py:

вот как у вас написано:

for user in get_user_model().objects.all():

а вот как должно быть написано:
for user in get_user_model().objects.filter(is_verified=True): # Проверка на верификацию пользователя

так мы берем пользователей которые прошли верификацию и только им шлем каждую минуту на почту письмо!


 

from django.template import Template, Context
from django.core.mail import send_mail
from django.contrib.auth import get_user_model
from publish.celery import app
from publish.models import Post

REPORT_TEMPLATE = """ 
                        Here's how you did till now: 
                        {% for post in posts %} 
                        "{{ post.title }}": viewed {{ post.view_count }} times | 
                        {% endfor %} 
                    """


@app.task
def send_view_count_report():
    for user in get_user_model().objects.filter(is_verified=True):  # Проверка на верификацию пользователя
        posts = Post.objects.filter(author=user)
        if not posts:
            continue
        template = Template(REPORT_TEMPLATE)
        send_mail(
            'Your Django_celery Project Activity',
            template.render(context=Context({'posts': posts})),
            'admin@localhost.ru',
            [user.email],
            fail_silently=False,
        )

@No_Name

@No_Name

Изменен No Name

@No_Name, Спасибо, поправил. Даже в мыслях не было, что учащиеся будут использовать не существующую почту.

Изменен Илья Перминов

Почему письмо отправляется только последнему зарегистрированному(при этом не подтвердившему верификацию) пользователю?

@Попов_Станислав, так быть не должно. Сейчас проверил, письма отправляются всем, не важен порядок регистрации. Попробуйте поискать ошибку. В случае если не найдете, отпишитесь, скинем ссылку на загрузку проекта и попробую уже я поискать ее.