Создание сайта на Django: Урок 51, асинхронные задачи, часть 2 (Отправка писем)
avatar
7 | (offline)
❤️‍🔥Notehunter Developer
Добавлено:
Категория: Руководства «Django»
Комментариев: 0

В прошлом уроке мы установили Redis, Celery: Создание сайта на Django: Урок 50, асинхронные задачи, часть 1 (Установка Celery, Redis)

А в этом уроке мы создадим асинхронную задачу, поэтому давайте приступим к ее созданию.

Функцию отправки email подтверждения мы создавали в уроке: Создание сайта на Django: Урок 29, регистрация с подтверждением по электронной почте в Django

Поэтому, давайте создадим в папке "services" нашего модуля "system", файл с задачами: tasks.py

Должно получиться вот так:

modules/system/services/tasks.py

from celery import shared_task

from modules.system.services.email import send_activate_email_message


@shared_task
def send_activate_email_task(email):
    """
    1. Получение из view регистрации
    2. Отправка через функцию send_activate_email_message
    """
    return send_activate_email_message(email)

Пояснение:

  • Импортируем декоратор @shared_task, для регистрации наших задач.
  • Создаем функцию на получение задачи, получаемый аргумент будет email.
  • Саму функцию мы будем вызывать во View.
  • А возвращать результатом будем выполнение самой функции send_activate_email_message из урока 29.

Но я все таки напомню, как выглядит сама функцияsend_activate_email_message:

modules/system/services/email.py

def send_activate_email_message(email):
    user = User.objects.get(email=email)
    current_site = Site.objects.get_current().domain
    subject = 'Активация аккаунта на сайте Django блог'
    message = render_to_string('modules/system/authenticated/email/activate-mail.html', {
        'user': user,
        'domain': current_site,
        'uid': urlsafe_base64_encode(force_bytes(user.pk)),
        'token': account_activation_token.make_token(user),
    })
    return user.email_user(subject, message)

Давайте поменяем методику вызова функции в RegisterCreateView

modules/system/views/authenticated.py

Меняем с 

from modules.system.services.email import send_activate_email_message

class RegisterCreateView(SuccessMessageMixin, CreateView):
    """
    Представление регистрации на сайте с формой регистрации
    """
    form_class = UserRegisterForm
    success_url = reverse_lazy('home')
    template_name = 'modules/system/authenticated/register.html'
    success_message = 'Вы успешно зарегистрировались. Подтвердите ваш email адрес. Может попасть в папку СПАМ!'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['title'] = 'Регистрация на сайте'
        return context

    def form_valid(self, form):
        if form.is_valid():
            user = form.save(commit=False)
            user.is_active = False
            user.save()
            send_activate_email_message(user.email) #edit
        return super().form_valid(form)

На следующий код:

from modules.system.services.tasks import send_activate_email_task

class RegisterCreateView(SuccessMessageMixin, CreateView):
    """
    Представление регистрации на сайте с формой регистрации
    """
    form_class = UserRegisterForm
    success_url = reverse_lazy('home')
    template_name = 'modules/system/authenticated/register.html'
    success_message = 'Вы успешно зарегистрировались. Подтвердите ваш email адрес. Может попасть в папку СПАМ!'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['title'] = 'Регистрация на сайте'
        return context

    def form_valid(self, form):
        if form.is_valid():
            user = form.save(commit=False)
            user.is_active = False
            user.save()
            send_activate_email_task.delay(user.email) #edit
        return super().form_valid(form)

Пояснение:

  • Импортируем нашу задачу send_activate_email_task
  • Добавляем delay, чтобы пропустить выполнение кода и передать его на выполнение в Celery
  • Аргументом передаем email пользователя.

А теперь давайте зарегистрируем пользователя и посмотрим на выполнение задачи

Запущу Celery с помощью команды: celery --app=backend worker --loglevel=info --pool=solo

И как результат запуска, мы увидим, что наша задача send_activate_email_task добавилась в пул задач Celery:

 
 -------------- celery@Razilator-PC v5.2.7 (dawn-chorus)
--- ***** ----- 
-- ******* ---- Windows-10-10.0.22000-SP0 2022-09-25 19:38:01
- *** --- * --- 
- ** ---------- [config]
- ** ---------- .> app:         backend:0x1f42b0cc130
- ** ---------- .> transport:   redis://127.0.0.1:6379/0
- ** ---------- .> results:     redis://127.0.0.1:6379/0
- *** --- * --- .> concurrency: 16 (solo)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** ----- 
 -------------- [queues]
                .> celery           exchange=celery(direct) key=celery


[tasks]
  . modules.system.services.tasks.send_activate_email_task

[2022-09-25 19:38:01,444: INFO/MainProcess] Connected to redis://127.0.0.1:6379/0
[2022-09-25 19:38:01,448: INFO/MainProcess] mingle: searching for neighbors
[2022-09-25 19:38:02,465: INFO/MainProcess] mingle: all alone
[2022-09-25 19:38:02,484: WARNING/MainProcess] C:\Users\Razilator\Desktop\Courses\App\venv\lib\site-packages\celery\fixups\django.py:203: UserWarning: Using settings.DEBUG leads to a memory
            leak, never use this setting in production environments!
  warnings.warn('''Using settings.DEBUG leads to a memory

[2022-09-25 19:38:02,485: INFO/MainProcess] celery@Razilator-PC ready.

А теперь я зарегистрирую пользователя:

После нажатия на кнопку регистрации, мы создали пользователя и отправили email активации, без какого-либо ожидания. В консоли Celery можно увидеть следующие действия:

[2022-09-25 19:40:50,228: INFO/MainProcess] Task modules.system.services.tasks.send_activate_email_task[3e78fcb1-b3c0-4d20-a113-6e781531bb6f] received
[2022-09-25 19:40:53,138: INFO/MainProcess] Task modules.system.services.tasks.send_activate_email_task[3e78fcb1-b3c0-4d20-a113-6e781531bb6f] succeeded in 2.906000000075437s: None

Ну и чтобы убедиться, вот письмо отправленное с помощью Celery и Redis:

А если мы зайдем в админ-панель Celery, то увидим нашу задачу со статусом выполнено (status: success):

Комментарии к статье 0
Комментариев нет
Форма добавления комментария (необходима регистрация)