Как отправить почту асинхронно с помощью асинхронного представления Django?

Я создаю проект, и хочу отправлять уведомление по электронной почте, когда пользователь совершает определенное действие.

Я провел небольшой поиск и смог добиться этого, используя threading.Thread. Поскольку Django теперь полностью поддерживает async view, я хочу сделать это с помощью async function.

Вот что я пробовал:

from asgiref.sync import sync_to_async
from django.core.mail import send_mail
from django.shortcuts import render
from myproj.settings import EMAIL_HOST_USER
import asyncio

asend_mail = sync_to_async(send_mail)

async def index(request):
    asyncio.create_task(
        asend_mail(
            subject='Test',
            message='Lorem ipsum',
            from_email=EMAIL_HOST_USER,
            recipient_list=['ezon@stackoverflow.dummy']
        )
    )
    return render(request, 'myapp/index.html', {})

Однако, когда я запрашиваю эту индексную страницу, я все еще получаю ответ ПОСЛЕ asend_mail coroutine complete.

Я попробовал следующую простую функцию async (из учебника), и все работает так, как ожидалось.

async def async_print():
    for num in range(1, 6):
        await asyncio.sleep(1)
        print(num)

async def index(request):
    asyncio.create_task(async_print())
    return render(request, 'myapp/index.html', {})

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

Я использую python 3.10.7, django 4.1.2, daphne 3.0.2 (как сервер, НЕ сервер разработки django).

Я новичок в области async/await. Буду признателен, если кто-нибудь сможет дать исчерпывающее объяснение.

Я бы попробовал использовать потоки (см.: https://realpython.com/intro-to-python-threading/ для справки)

Я использовал его для загрузки 1000's (больших) файлов на ведро S3. Это было примерно в 70 раз быстрее, чем делать это последовательно.

Идея заключается в том, что эта почтовая задача будет обернута в поток, и поток будет выпущен, а ваш код продолжит работу с этого момента, а не будет ждать завершения задачи (в потоке).

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