如何使用 Celery(无第三方包)发送 Django 的密码重置邮件?
How to send Django's password reset email using Celery (without third-party package)?
首先我知道这个问题之前已经回答过 which use a third-party package django-celery-email,但我想弄清楚如何在不依赖任何第三方库的情况下完成这样的工作。
所以我需要用 Celery 异步发送密码重置邮件。
我的 forms.py
文件如下所示:
from django import forms
from accounts.tasks import send_mail
from django.contrib.auth.forms import PasswordResetForm as PasswordResetFormCore
class PasswordResetForm(PasswordResetFormCore):
email = forms.EmailField(max_length=254, widget=forms.TextInput(
attrs={
'class': 'form-control',
'id': 'email',
'placeholder': 'Email'
}
))
def send_mail(self, subject_template_name, email_template_name,
context, from_email, to_email, html_email_template_name=None):
"""
This method is inherating Django's core `send_mail` method from `PasswordResetForm` class
"""
super().send_mail(subject_template_name, email_template_name,
context, from_email, to_email, html_email_template_name)
我正在尝试通过 Celery 从 PasswordResetForm
class 的 send_mail
方法发送邮件。我的意思是用 Celery 调用 super().send_mail(...)
。我的 Celery 的 tasks.py
文件中也有一个 send_mail
函数,我试图将 super().send_mail
方法作为参数传递给它来调用它从那里开始。
现在我的 tasks.py
文件看起来像这样:
from __future__ import absolute_import, unicode_literals
@shared_task
def send_mail():
pass
我将 RabbitMQ
与 Celery
一起用作消息代理
好的,我已经找到了一个可行的解决方案。这是我的解决方案。
我已经改forms.py
如下
from django import forms
from accounts.tasks import send_mail
from django.contrib.auth.forms import PasswordResetForm as PasswordResetFormCore
class PasswordResetForm(PasswordResetFormCore):
email = forms.EmailField(max_length=254, widget=forms.TextInput(
attrs={
'class': 'form-control',
'id': 'email',
'placeholder': 'Email'
}
))
def send_mail(self, subject_template_name, email_template_name, context,
from_email, to_email, html_email_template_name=None):
context['user'] = context['user'].id
send_mail.delay(subject_template_name=subject_template_name,
email_template_name=email_template_name,
context=context, from_email=from_email, to_email=to_email,
html_email_template_name=html_email_template_name)
变化后的tasks.py
如下
from __future__ import absolute_import, unicode_literals
from accounts.models import User
from django.contrib.auth.forms import PasswordResetForm
@shared_task
def send_mail(subject_template_name, email_template_name, context,
from_email, to_email, html_email_template_name):
context['user'] = User.objects.get(pk=context['user'])
PasswordResetForm.send_mail(
None,
subject_template_name,
email_template_name,
context,
from_email,
to_email,
html_email_template_name
)
与上一个类似,但采用浓缩方式
forms.py
"""users/forms.py"""
from django.contrib.auth.forms import PasswordResetForm
from users.tasks import send_reset_password_email_async
class CustomPasswordResetForm(PasswordResetForm):
"""
Extend Auth Form for adding support to Async email using Celery
"""
# keys -> email, domain, site_name, uid, user, token, protocol
context = args[2]
context['user'] = context['user'].pk
send_reset_password_email_async.delay(*args, **kwargs)
tasks.py
"""users/tasks.py"""
from users.models import User
from celery import shared_task
from django.contrib.auth.forms import PasswordResetForm
@shared_task
def send_reset_password_email_async(*args, **kwargs):
"""
Description
-----------
- User must be restore from None to object.
- Send the reset password email as async task
"""
# Restoring user
context = args[2]
context['user'] = User.objects.get(pk=context['user'])
PasswordResetForm.send_mail(None, *args, **kwargs)
最后使用开头扩展的形式
urls.py
"""proj/urls.py"""
from django.urls import path, include,
urlpatterns = [
# ...
path(
'password_reset/',
auth_views.PasswordResetView.as_view(
form_class=CustomPasswordResetForm, # <-- async email support
# ...
),
name='password_reset'
),
# ...
]
已测试!
首先我知道这个问题之前已经回答过
所以我需要用 Celery 异步发送密码重置邮件。
我的 forms.py
文件如下所示:
from django import forms
from accounts.tasks import send_mail
from django.contrib.auth.forms import PasswordResetForm as PasswordResetFormCore
class PasswordResetForm(PasswordResetFormCore):
email = forms.EmailField(max_length=254, widget=forms.TextInput(
attrs={
'class': 'form-control',
'id': 'email',
'placeholder': 'Email'
}
))
def send_mail(self, subject_template_name, email_template_name,
context, from_email, to_email, html_email_template_name=None):
"""
This method is inherating Django's core `send_mail` method from `PasswordResetForm` class
"""
super().send_mail(subject_template_name, email_template_name,
context, from_email, to_email, html_email_template_name)
我正在尝试通过 Celery 从 PasswordResetForm
class 的 send_mail
方法发送邮件。我的意思是用 Celery 调用 super().send_mail(...)
。我的 Celery 的 tasks.py
文件中也有一个 send_mail
函数,我试图将 super().send_mail
方法作为参数传递给它来调用它从那里开始。
现在我的 tasks.py
文件看起来像这样:
from __future__ import absolute_import, unicode_literals
@shared_task
def send_mail():
pass
我将 RabbitMQ
与 Celery
好的,我已经找到了一个可行的解决方案。这是我的解决方案。
我已经改forms.py
如下
from django import forms
from accounts.tasks import send_mail
from django.contrib.auth.forms import PasswordResetForm as PasswordResetFormCore
class PasswordResetForm(PasswordResetFormCore):
email = forms.EmailField(max_length=254, widget=forms.TextInput(
attrs={
'class': 'form-control',
'id': 'email',
'placeholder': 'Email'
}
))
def send_mail(self, subject_template_name, email_template_name, context,
from_email, to_email, html_email_template_name=None):
context['user'] = context['user'].id
send_mail.delay(subject_template_name=subject_template_name,
email_template_name=email_template_name,
context=context, from_email=from_email, to_email=to_email,
html_email_template_name=html_email_template_name)
变化后的tasks.py
如下
from __future__ import absolute_import, unicode_literals
from accounts.models import User
from django.contrib.auth.forms import PasswordResetForm
@shared_task
def send_mail(subject_template_name, email_template_name, context,
from_email, to_email, html_email_template_name):
context['user'] = User.objects.get(pk=context['user'])
PasswordResetForm.send_mail(
None,
subject_template_name,
email_template_name,
context,
from_email,
to_email,
html_email_template_name
)
与上一个类似,但采用浓缩方式
forms.py
"""users/forms.py"""
from django.contrib.auth.forms import PasswordResetForm
from users.tasks import send_reset_password_email_async
class CustomPasswordResetForm(PasswordResetForm):
"""
Extend Auth Form for adding support to Async email using Celery
"""
# keys -> email, domain, site_name, uid, user, token, protocol
context = args[2]
context['user'] = context['user'].pk
send_reset_password_email_async.delay(*args, **kwargs)
tasks.py
"""users/tasks.py"""
from users.models import User
from celery import shared_task
from django.contrib.auth.forms import PasswordResetForm
@shared_task
def send_reset_password_email_async(*args, **kwargs):
"""
Description
-----------
- User must be restore from None to object.
- Send the reset password email as async task
"""
# Restoring user
context = args[2]
context['user'] = User.objects.get(pk=context['user'])
PasswordResetForm.send_mail(None, *args, **kwargs)
最后使用开头扩展的形式 urls.py
"""proj/urls.py"""
from django.urls import path, include,
urlpatterns = [
# ...
path(
'password_reset/',
auth_views.PasswordResetView.as_view(
form_class=CustomPasswordResetForm, # <-- async email support
# ...
),
name='password_reset'
),
# ...
]
已测试!