Как отправить почту асинхронно с помощью асинхронного представления 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 раз быстрее, чем делать это последовательно.
Идея заключается в том, что эта почтовая задача будет обернута в поток, и поток будет выпущен, а ваш код продолжит работу с этого момента, а не будет ждать завершения задачи (в потоке).