记录一下Django发送异步邮件的过程
整个项目目录如下图所示
homework为整个项目的名称,t06为app名称1、分别在homework和t06下的__init__文件中的配置
from __future__ import absolute_import
# 使用异步的参数
from .celery import app as celery_app
# python使用mysql的必备参数
import pymysql
pymysql.install_as_MySQLdb()
import pymysql
pymysql.install_as_MySQLdb()
2、在settings.py文件中的部分配置
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
't06',
# 在INSTALL_APPS中需加入djcelery模块(必须)
'djcelery'
]
#1、数据库连接
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',#引擎此处采用mysql的
'NAME': '要连接的数据库的名字',#name即数据库的名字,
'PORT': 3306,#mysql数据的端口,默认为3306
'HOST': "地址",#“host”即主机地址
'USER': "用户名", #“USER”指的是数据库注册用户名
'PASSWORD': '数据库密码'#数据库的密码
}
}
#2、缓存设置,主要用来记录激活邮件中发送的信息
SESSION_COOKIE_NAME = "session_id"
#此处采用Redis来存储缓存信息
CACHES = {
#此处为默认选择
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/1",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
},
#此处为自定义选择
"user": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://127.0.0.1:6379/2",
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
}
},
}
#3、邮件发送者的配置
EMAIL_USE_SSL = True
EMAIL_HOST = 'smtp.qq.com' # 如果是 163 改成 smtp.163.com
EMAIL_PORT = 465
EMAIL_HOST_USER = "xxxxxxxxx@qq.com" # 发送者的帐号
EMAIL_HOST_PASSWORD = "授权码" # 授权码,不是邮箱密码(****)
DEFAULT_FROM_EMAIL = EMAIL_HOST_USER
#4、异步执行的配置,需要导入djcelery模块
import djcelery
djcelery.setup_loader()
BROKER_URL = 'redis://localhost:6379/1'
CELERY_CONCURRENCY = 2 # (设置worker的并发数量)
CELERY_RESULT_BACKEND = 'redis://localhost:6379/2'
CELERY_TASK_SERIALIZER = 'json' # 任务序列化和反序列化使用json
CELERY_RESULT_SERIALIZER = 'json' # 结果序列化为json
CELERYBEAT_SCHEDULE = {
'every-ten-second-run-my-task': {
'task': 't06.tasks.my_task',#task程序的位置
'schedule': timedelta(seconds=10),
'args': (2,)
},
}
3、在celery.py文件中的配置
# -*- coding: utf-8 -*-
from __future__ import absolute_import #绝对路径导入
from celery import Celery
import os
#设置系统的环境配置用的是Django的
from django.conf import settings
os.environ.setdefault("DJANGO_SETTING_MODULE", "homework.settings")
#实例化celery
app = Celery('mycelery')
app.conf.timezone = "Asia/Shanghai"
#指定celery的配置来源 用的是项目的配置文件settings.py
app.config_from_object("django.conf:settings")
#让celery 自动去发现我们的任务(task)
app.autodiscover_tasks(lambda : settings.INSTALLED_APPS) #你需要在app目录下 新建一个叫tasks.py(一定不要写错)文件y
4、在tasks.py文件中的配置(文件名必须为tasks,是celery文件中规定的)
# -*- coding: utf-8 -*-
from celery import task
import time
from django.conf import settings
from django.core.mail import send_mail
from django.http import HttpResponse
from django.template.loader import get_template
@task
def send_my_mail(title,message,email):
email_from = settings.DEFAULT_FROM_EMAIL
recivies = [
email
]
url = message
# 渲染
template = get_template('temp.html')
html_str = template.render({'url':url})
print(html_str)
#发送邮件的函数,Django中自带
send_mail(
title,message,email_from,recivies
)
return HttpResponse('ok')
5、在views.py文件中的执行注册激活功能的函数
register函数用于生成验证链接并发送邮件,index函数用于激活用户
其中get_user,MyUser,get_unique_name,send_my_mail(即task.py文件中的函数)均为自定义表或函数
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from .tasks import *
from django.contrib.auth import authenticate, login, logout, update_session_auth_hash
from django.http import HttpResponse, HttpResponseNotAllowed, JsonResponse
from django.shortcuts import render,redirect
from django.urls import reverse
from .util import get_unique_name
from .models import MyUser
from django.core.cache import cache, caches
#设置使用的缓存,此处的“user”即为settings中CACHE中自定义的缓存容器
user_cache = caches["user"]
def index(req):
if req.method =='GET':
# 得到验证码
verification = req.GET.get('verification')
# print(message)
uname = req.GET.get('uname')
# print(uname)
print(get_user(verification))
if get_user(verification):
user001 = MyUser.objects.filter(username=uname).update(
is_active=True
)
data = req.POST.get('uname')
if data == None:
data={
'uname':'游客'
}
return render(req,'index.html',{"error_msg":'欢迎游客'})
def register(req):
if req.method =='GET':
return render(req,'register.html',{'error_msg':''})
elif req.method == 'POST':
uname = req.POST.get('uname')
print(uname)
email = req.POST.get('email')
phone = req.POST.get('phone')
pwd = req.POST.get('pwd')
print(pwd)
confirm_pwd = req.POST.get('confirm_pwd')
print('输入完成')
# 验证用户名是否符合
# 验证密码是否正确
if uname and len(uname)<3:
return render(req,'register.html',{'error_msg':'用户名长度至少为3'})
elif pwd and pwd == confirm_pwd:
pass
else:
return render(req,'register.html',{'error_msg':'密码与确认密码不一致'})
# 验证用户名,手机号,邮箱是否已存在
if MyUser.objects.filter(username=uname).exists():
return render(req,'register.html',{'error_msg':'用户名已存在'})
elif MyUser.objects.filter(email=email).exists():
return render(req,'register.html',{'error_msg':'邮箱已存在'})
elif MyUser.objects.filter(phone=phone).exists():
return render(req,'register.html',{'error_msg':'手机号已存在'})
else:
print('验证完毕')
user = MyUser.objects.create_user(
username=uname,
password=pwd,
phone = phone,
email=email,
is_active = False
)
# 注册同时生成激活邮件
title = '验证邮件'
schema = "https://" if req.is_secure() else "http://"
verification = str(get_unique_name())
# 设置缓存
user_cache.set(verification, uname, 60 * 60)
url_path = "/t06/index?verification="+verification+'&&uname='+str(uname)
#生成验证的链接
url_message = "{schema}{host_and_port}{url_path}".format(
schema=schema,
host_and_port=req.get_host(),
url_path=url_path
)
send_my_mail.delay(title=title, message=url_message, email=email)
return render(req,'index.html',{'error_msg':'注册成功,请激活邮件'})
else:
return render(req,'register,html',{'error_msg':''})
a、get_user函数,用于点击激活链接时查询缓存的操作,此处写在views.py文件下
def get_user(message):
# 去缓存尝试拿数据
res = user_cache.get(message)
if res:
print("缓存的")
return True
b、get_unique_name函数,用于生成独一无二的验证码,此处写在views.py文件下
import random
import uuid
import hashlib
def get_unique_name():
uuid_str = str(uuid.uuid4()).encode('utf-8')
md5 = hashlib.md5()
md5.update(uuid_str)
return md5.hexdigest().lower()
c、自定义的MyUser用户表,写在models.py文件下
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.contrib.auth.models import AbstractUser
from django.db import models
#继承了Django自带的user表
class MyUser(AbstractUser):
phone = models.CharField(
max_length=13,
verbose_name='手机号',
unique=True,
null=True
)
email = models.EmailField(
null=False
)
启动程序
1、在manage.py文件所在目录下启动程序
python manage.py runserver 0.0.0.0:9000
2、启动异步的程序(一定要启动!!!!!!!!!!!!!!)
python manage.py celery worker --loglevel=info
补充
由于自定义了用户表,所以验证函数authenticate也需要重新定义,此处写在auth.py文件中
# -*- coding: utf-8 -*-
from django.contrib.auth.backends import ModelBackend
from .models import MyUser
class MyBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, phone =None,email=None):
if not password:
return Exception('密码必须填写')
user = None
try:
user = MyUser.objects.get(username=username)
except MyUser.DoesNotExist:
try:
user = MyUser.objects.get(phone=username)
except MyUser.DoesNotExist:
# try:
# user=MyUser.objects.get(email=username)
# except MyUser.DoesNotExist:
return None
if user and user.check_password(password) and user.is_active:
return user
else:
return None