Возможность планировать задачи внутри приложения Python Django имеет решающее значение при разработке веб-приложений, веб-приложения обычно должны выполнять определенные задачи, такие как: (1) обновление базы данных новой информацией или (2) отправка определенных уведомлений - вне общего приложения поток.

Эти задачи должны выполняться в фоновом режиме, и приложение должно инстинктивно знать, когда их выполнять, через определенные промежутки времени. В этом руководстве мы шаг за шагом рассмотрим, как это сделать, но прежде чем мы начнем, у нас есть некоторые предварительные условия:

  1. Завершенное приложение Django (я не буду подробно рассказывать, как настроить приложение Django в этом руководстве, ознакомьтесь с предыдущей статьей, в которой рассказывается о настройке приложения Django)
  2. Мы будем делать это в Ubuntu 20.04 - некоторые шаги могут отличаться, если вы используете другую операционную систему.

Шаги, которым мы будем следовать в этом руководстве

  • Установите Redis на Ubuntu 20.04 (для Celery требуется брокер)
  • Кодируйте задачи, которые сельдерей должен выполнять по расписанию
  • Создайте файлы инициации для сельдерея
  • Настройка параметров Celery в проекте Django
  • Запускаем Celery (режим разработки)
  • Запускаем Celery (производственное приложение)

Установка Redis Broker в ОС Ubuntu 20.04

Для работы Celery нужен брокер (например, Redis sever). Хорошая новость заключается в том, что Redis действительно легко установить, поэтому приступим:

Начните с обновления пакетов

sudo apt update

Установить Redis

sudo apt install redis-server

После установки Redis вам необходимо внести небольшие изменения в файл конфигурации:

Откройте файл конфигурации:

sudo nano /etc/redis/redis.conf

Прокрутите файл вниз и найдите контролируемую директиву, замените «no» на «systemd» следующим образом:

............
#   supervised auto    - detect upstart or systemd method based on
#                        UPSTART_JOB or NOTIFY_SOCKET environment variables
# Note: these supervision methods only signal "process is ready."
#       They do not enable continuous liveness pings back to your supervisor.
supervised systemd
# If a pid file is specified, Redis writes it where specified at startup
# and removes it at exit.
#
.............

Найдите в файле следующую строку:

bind 127.0.0.1 ::1

Убедитесь, что он не закомментирован, удалите любой символ # перед строкой, если он есть. В моей установке строка уже была раскомментирована, поэтому я ничего не делал.

Закройте файл и сохраните все изменения.

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

sudo systemctl restart redis.service

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

Failed to restart redis.service: Unit redis.service not found.

Если вы получили это, вам просто нужно включить redis-server, который автоматически создаст символическую ссылку на redis.service. Выполните следующую команду (ЕСЛИ У ВАС ОШИБКА ВЫШЕ)

sudo systemctl enable redis-server

Затем вы можете повторно запустить: sudo systemctl restart redis.service без проблем.

Наконец, проверьте статус услуги:

sudo systemctl status redis

Вы должны увидеть это: с зеленым светом

Напишите задачи, которые необходимо запланировать с помощью сельдерея

Задача, которую мы планируем запланировать, - это рассылка периодических электронных писем пользователям нашего приложения в зависимости от их предпочтений. С этой задачей нам нужно будет: (1) взаимодействовать с нашей базой данных Django, моделями и (2) отправить электронное письмо, чтобы мы могли проверить, что задача произошла в запланированное время.

Мы будем работать с нашим веб-приложением Careers-Portal, отправляя по электронной почте конкретные вакансии пользователям, которые запросили уведомления по электронной почте. Начнем с файловой структуры нашего проекта.

Файлы, выделенные полужирным шрифтом, будут добавляться или изменяться по мере продвижения по этому руководству. Чтобы создать новые задачи для планирования, нам нужно добавить код в каталоги проекта в файл с именем - tasks.py, это новый файл.

skoloapp (root directory)
|
|_______ skoloapp (project directory)
|           |________ __init__.py (* modifications to this file)
|           |________ settings.py (* modifications to this file)
|           |________ urls.py
|           |________ celery.py (* new file we will add)
|           |________ OTHER FILES
|
|_______ jobs (app directory)
|           |________ __init__.py
|           |________ admin.py
|           |________ apps.py
|           |________ models.py
|           |________ tasks.py (* new file we will add)
|           |________ OTHER FILES
|
|_______ OTHER app directories

Содержимое файла tasks.py: для планирования рассылки из базы данных:

from __future__ import absolute_import, unicode_literals
from celery import task
#imports needed for the functions
from django.conf import settings
from django.core.mail import EmailMultiAlternatives
from django.template.loader import get_template
from .models import *
from django.contrib.auth.models import User
from users.models import *
def sendEmail(email, subject, to_email):
    #Logic to send an email here ........
@task()
def scheduledTask():
    #Get Subscriptions
    notifications = JobNotifications.objects.all()
    for nx in notifications:
        if nx.status == 'ACTIVE':
            selection = nx.subscribed_category
the_company = Company.objects.get(uniqueId='139260d2')
            jobs = Jobs.objects.filter(company=the_company, category__title__contains=selection)[:3]
subject = '[Careers Portal] Weekly Job Notifications'
email_jobs = {
            "title": "Job Notifications from Careers Portal",
            "shortDescription": "Thank you for subscribing to Careers Portal, job notifications. For more jobs visit https://careers-portal.co.za",
            "subtitle": "Careers Portal - The latest job opportunities, updated weekly",
            "jobs": jobs
            }
sendEmail(email_jobs, subject, [nx.subscribed_user.email])

Логика отправки электронного письма здесь не включена, но она должна быть простой и не является целью этого руководства. Следует отметить следующее: (1) импорт в верхней части файла, импорт __future__ должен быть первым импортом в файле, (2) декоратор @task - для включения во все функции, которые будут запланированы. . У вас может быть несколько функций в одном файле, если вы хотите запланировать их - включите декоратор, (3) вы можете получить доступ к моделям и базе данных Django, чтобы использовать их для своих задач по мере необходимости.

Если вы хотите узнать больше об отправке писем из приложения Django, ознакомьтесь с предыдущим руководством по отправке писем из Python Django.

Настройка файлов сельдерея

Теперь мы можем перейти в каталог проекта, создать новый файл с именем celery.py и добавить следующий код:

from __future__ import absolute_import, unicode_literals
import os
from celery import Celery
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'skoloapp.settings')
app = Celery('skoloapp')
app.config_from_object('django.conf:settings', namespace='CELERY')
app.autodiscover_tasks()
@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))

Опять же, импорт __future__ должен быть первым в файле. Замените «skoloapp» названием своего проекта.

Затем откройте __init__.py и добавьте следующий код:

from __future__ import absolute_import, unicode_literals
from .celery import app as celery_app
__all__ = ['celery_app']

Настройте параметры Celery для приложения Django

Наконец, нам нужно будет добавить настройки сельдерея в наш файл settings.py. Откройте файл и добавьте следующий код:

from celery.schedules import crontab
#.....
# Rest of the file
#....
#CELERY SETTINGS
CELERY_BROKER_URL = 'redis://localhost:6379'
CELERY_RESULT_BACKEND = 'redis://localhost:6379'
CELERY_ACCEPT_CONTENT = ['application/json']
CELERY_RESULT_SERIALIZER = 'json'
CELERY_TASK_SERIALIZER = 'json'
CELERY_TIMEZONE = 'Africa/Johannesburg'
CELERY_BEAT_SCHEDULE = {
'task-number-one': {
'task': 'jobs.tasks.scheduledTask',
'schedule': crontab(minute='*/5')
}
}

Добавьте импорт crontab вверху файла, и вы можете разместить настройки внизу файла. Не забудьте заменить часовой пояс на свой собственный tomezone и установить расписание соответствующим образом. Я решил запланировать эту задачу каждые пять минут crontab (minute = '* / 5') = ›Здесь представлены все минуты, которые делятся на 5. Подробнее о настройке разных расписаний читайте здесь.

Запустить режим развития сельдерея

Прежде чем мы сможем запустить Celery, нам нужно установить его в нашей виртуальной среде, нам также необходимо установить redis для python, поэтому выполните следующие команды:

pip install redis
pip install celery==4.4.2

Если установка прошла успешно, мы можем протестировать наши запланированные задачи, нам нужно только подождать около 5 минут, чтобы убедиться, что задача была выполнена без проблем.

Выполните эту команду, чтобы запустить Celery.

celery -A skoloapp worker -l info -B

Если вы столкнулись с проблемами на этом этапе, просто убедитесь, что вы снова прошли обучение и проверьте все шаги. Вы также можете посмотреть наш видеоурок на Youtube:

Запустить сельдерей - производственное приложение

Чтобы запустить сельдерей в производственной среде, вам необходимо сделать следующее:

Начните с установки супервизора в Ubuntu

sudo apt-get install supervisor

Создайте файл конфигурации для Celery worker

/etc/supervisor/conf.d/celery_proj_worker.conf

Вставьте это в этот файл

; ==================================
; celery worker supervisor example
; ==================================
; the name of your supervisord program
[program:skoloworker]
; Set full path to celery program if using virtualenv
command=/home/zatosh/dev/skolo/skolo/skoloenv/bin/celery -A proj worker -l info
; The directory to your Django project
directory=/home/zatosh/dev/skolo/skolo/skoloapp
; If supervisord is run as the root user, switch users to this UNIX user account before doing any processing.
user=zatosh
; Supervisor will start as many instances of this program as named by numprocs
numprocs=1
; Put process stdout output in this file stdout_logfile=/var/log/celery/proj_worker.log
; Put process stderr output in this file stderr_logfile=/var/log/celery/proj_worker.log
; If true, this program will start automatically when supervisord is started
autostart=true
; May be one of false, unexpected, or true. If false, the process will never be autorestarted. If unexpected, the process will be restart when the program exits with an exit code that is not one of the exit codes associated with this process’ configuration (see exitcodes). If true, the process will be unconditionally restarted when it exits, without regard to its exit code.
autorestart=true
; The total number of seconds which the program needs to stay running after a startup to consider the start successful.
startsecs=10
; Need to wait for currently executing tasks to finish at shutdown. ; Increase this if you have very long running tasks.
stopwaitsecs = 600 
; When resorting to send SIGKILL to the program to terminate it ; send SIGKILL to its whole process group instead, taking care of its children as well.
killasgroup=true
; if your broker is supervised, set its priority higher so it starts first
priority=998

Замените жирные строки своим (1) путем к файлам сельдерея, (2) каталогом проекта и (3) пользователем.

Затем создайте файл конфигурации сельдерея

/etc/supervisor/conf.d/celery_proj_beat.conf

Вставьте это в файл

; ================================
;  celery beat supervisor example
; ================================
; the name of your supervisord program
[program:skolobeat]
; Set full path to celery program if using virtualenv
command=/home/zatosh/dev/skolo/skolo/skoloenv/bin/celery -A proj beat -l info
; The directory to your Django project
directory=/home/zatosh/dev/skolo/skolo/skoloapp
; If supervisord is run as the root user, switch users to this UNIX user account before doing any processing.
user=zatosh
; Supervisor will start as many instances of this program as named by numprocs
numprocs=1
; Put process stdout output in this file stdout_logfile=/var/log/celery/proj_beat.log
; Put process stderr output in this file stderr_logfile=/var/log/celery/proj_beat.log
; If true, this program will start automatically when supervisord is started
autostart=true
; May be one of false, unexpected, or true. If false, the process will never be autorestarted. If unexpected, the process will be restart when the program exits with an exit code that is not one of the exit codes associated with this process’ configuration (see exitcodes). If true, the process will be unconditionally restarted when it exits, without regard to its exit code.
autorestart=true
; The total number of seconds which the program needs to stay running after a startup to consider the start successful.
startsecs=10
; if your broker is supervised, set its priority higher so it starts first
priority=999

Замените жирные строки своим (1) путем к файлам сельдерея, (2) каталогом проекта и (3) пользователем.

Перейдите в / var / log /

cd /var/log/

Создайте каталог для сельдерея, если он еще не существует

sudo mkdir celery && cd celery

Создать файлы журнала

sudo touch proj_worker.log
sudo touch proj_beat.log

Обновить супервизора

sudo supervisorctl reread
sudo supervisorctl update

Запустить сервис

sudo supervisorctl start skoloworker
sudo supervisorctl start skolobeat

Проверить статус услуги

sudo supervisorctl status skoloworker
sudo supervisorctl status skolobeat

Больше контента на plainenglish.io