django用celery+redis实现异步发送验证码
(注:当前python的版本为3.6,3.7版本可能会有一个bug)
首先我们先能成功发送邮件,不用celery,在创建django项目
django-admin startproject itemname
cd到项目根目录下:
cd itemname
python manage.py startapp appname
首先在django项目的settings添加以下的内容:
# 注册app
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'account.apps.AccountConfig',
'database.apps.DatabaseConfig',
'appname'
]
# 添加发送邮件的一些配置
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.qq.com' # 这里我选的是QQ邮箱
EMAIL_PORT = 25 # 发件箱的smtp服务器端口
EMAIL_HOST_USER = '*****@qq.com' # 你的 QQ 邮箱
EMAIL_HOST_PASSWORD = '**********'# qq邮箱授权码,下边会说怎么获取授权码
EMAIL_USE_TLS = True # 这里必须是 True,否则发送不成功
EMAIL_FROM = '********@qq.com' # 你的 QQ 邮箱
获取qq邮箱的授权码
打开qq邮箱,登陆、点击设置-----账户
第一个POP3/SMTP和第二个IMAP/SMTP开启,按照指引流程便可得到授权码
在app下创建一个email.py的文件
from django.conf import settings
def send_email(email):
code = ''.join(random.sample(list('123456789qazwsxedcrfvtgbyhnujmikolp'), 5)).upper()
email_title = '邮件标题'
email_body = '您的验证码为%s'%(code)# 邮件内容
sender = settings.EMAIL_FROM
send_status = send_mail(email_title,
email_body,
sender,# 发送邮件的邮箱
[email]) #发送到的邮箱
if send_status:
return '邮件发送成功'
else:
return '邮件发送失败'
以上便是可以发送邮件了,接下来我们加入celery来实现异步发送验证码
celery介绍:
-
celery是一个功能完备,即插即用的任务队列
-
celery适用于处理异步问题,比如发送邮件、图像处理、文件上传等比较耗时的操作,我们可以将其异步执行,这样用户就不需要等待很久,可以提高用户体验
-
详细容请点击查看celery参考文档
Celery的架构
Celery的架构由三部分组成,消息中间件(message broker),任务执行单元(worker)和任务执行结果存储(task result store)组成。
消息中间件
Celery本身不提供消息服务,但是可以方便的和第三方提供的消息中间件集成,包括,RabbitMQ,Redis,MongoDB等,这里我先去了解RabbitMQ,Redis。
任务执行单元
Worker是Celery提供的任务执行的单元,worker并发的运行在分布式的系统节点中
任务结果存储
Task result store用来存储Worker执行的任务的结果,Celery支持以不同方式存储任务的结果,包括Redis,MongoDB,Django ORM,AMQP等,这里我先不去看它是如何存储的,就先选用Redis来存储任务执行结果。
注:本教程使用的是redis来存储
首先安装redis和celery
pip install celery
pip install django-redis
安装完毕后,首先配置celery,在项目目录下创建celery.py(注:和settings是同一个目录下)
import os
from celery import Celery
# 为celery程序设置默认的django设置模块
os.environ.setdefault('DJANGO_SETTINGS_MODULE','itemname.settings')
broker = 'redis://127.0.0.1:6379/1' # 将要进行的任务
backend = 'redis://127.0.0.1:6379/2' # 返回的结果
app = Celery('itemname', broker=broker, backend=backend)
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))
broker是一个消息传输的中间件,每当应用程序调用celery的异步任务的时候,会向broker传递消息,随后celery的worker将会取到消息,这个中间件可以看作是一个消息队列。
通常程序发送的消息,可能都不知道对方是什么时候接受了。为此,celery实现了一个backend,用于存储这些消息以及celery执行的一些消息和结果。
celery文件编写完毕,然后在app目录下编写异步任务------创建tasks.py文件。
from celery import shared_task
from django.conf import settings
from django.core.mail import send_mail
import random
@shared_task
def send_active_email(email):
code = ''.join(random.sample(list('123456789qazwsxedcrfvtgbyhnujmikolp'), 5)).upper()
email_title = '邮件标题'
sender = settings.EMAIL_FROM
message = '您的验证码为%s' % (code)
receiver = [email]
send_mail(subject,message,sender,receiver)
这个就是celery要做的任务啦
然后在视图中写一些代码来运行程序
from account.tasks import send_active_email
def register_handle(request):
send_active_email.delay('[email protected]')
return HttpResponse('程序执行成功')
配置好url
from django.urls import path
from account import views
urlpatterns = [
path('register_handle/',views.register_handle,name='register_handle')
]
然后改写根应用文件夹里的init.py,将整个文件改为:
from .celery import app as celery_app
__all__ = ['celery_app']
启动celery的服务,在项目根目录输入:
celery -A itemname worker -l info
运行程序,然后在网页上输入链接就可以了。
这时可能celery会报错,邮件发送成功的则不需要进行下方操作:
解决方法:
安装eventlet库
pip install eventlet
然后重新运行celery服务
celery -A itemname worker -l info -P eventlet
这样这个报错就可以解决了。
如果大家觉得我写的对你有用,可以点一下关注,点个赞。如果大家出现的其他的bug,请在下方评论出来,谢谢。