一. 注册基本逻辑
1. user子应用 定义 注册视图类
import re
from django.conf import settings
from django.http import HttpResponse
from django.shortcuts import render, redirect
from django.urls import reverse
# 显示异常,但不会报错
from django.views.generic import View
from user.models import User
class RegisterView(View):
"""注册"""
def get(self, request):
"""显示注册页面"""
return render(request, 'register.html')
def post(self, request):
"""进行注册处理"""
# 1. 接收数据
username = request.POST.get('user_name')
password = request.POST.get('pwd')
email = request.POST.get('email')
allow = request.POST.get("allow") # 复选框,如果选择参数值就是 'on'
# 2. 进行校验
if not all([username, password, email]): # all函数,参数是可迭代的,都为True,则为True
# 数据不完整
return render(request, 'register.html', {"errmsg": "消息不完整"})
# 校验邮箱
if not re.match(r'^[a-z0-9][\w.\-]*@[a-z0-9\-]+(\.[a-z]{2,5}){1,2}$', email):
return render(request, 'register.html', {"errmsg": "邮箱格式不合法"})
# 校验是否勾选协议
if allow != 'on':
return render(request, 'register.html', {"errmsg": "请同意协议"})
# 校验用户名是否重复
try:
user = User.objects.get(username=username)
except User.DoesNotExist:
# 用户名不存在
user = None
if user:
# 用户名已存在
return render(request, 'register.html', {"errmsg": "用户名已存在"})
# 3. 进行业务处理: 进行用户注册
# 使用django的内置认证可以直接使用 create_user方法保存
user = User.objects.create_user(username, email, password) # 执行这句代码已经保存到数据库了
user.is_active = 0 # 额外 设置账号未激活
user.save() # 额外 保存
# 4. 返回应答,跳转到首页
# reverse反向解析(主urls定义的别名 : 子url定义的别名)
# return redirect(reverse('goods:index')) #此时还没首页,后面创建首页后自己放开注释
return HttpResponse("首页")
2. user子应用定义 注册路由
from django.conf.urls import url
from apps.user import views
from apps.user.views import RegisterView
app_name="user" # 指定命名空间
urlpatterns = [
url(r'^register$',RegisterView.as_view(),name="register"), # 注册
]
3. 注册页面源码
正在补充
二. 用户激活
注册后,需要用户点击邮件中的链接账号才能生效
为了保证安全,需要对用户的身份信息加密
1. 安装第三方库
pip install itsdangerous==1.1
2. 生成 激活 用的token
# 在注册类中生成token
from django.conf import settings
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer, SignatureExpired
class RegisterView(View):
"""注册"""
def get(self, request):
"""显示注册页面"""
...
def post(self, request):
"""进行注册处理"""
# 1. 接收数据
...
# 2. 进行校验
...
# 3. 进行业务处理: 进行用户注册
...
user.save() # 额外 保存
# 发送激活邮件,包含激活链接: http://127.0.0.1"8000/user/active/3
# 激活链接中需要包含用户的身份信息,并且要把身份信息进行加密
# 加密用户的身份信息,生成激活token
# 加密对象( 随机字符串,过期时间(秒) )
seriaizer = Serializer(settings.SECRET_KEY, 3600)
info = {'confirm': user.id}
toeken = seriaizer.dumps((info)) # dumps: 加密
# 发邮件
# 4. 返回应答,跳转到首页
...
3. user子应用定义 激活验证类
(1). 定义激活类
class ActiveView(View):
"""用户激活"""
def get(self,request,token):
"""进行用户激活"""
# 进行解密,获取要激活的用户信息
seriaizer = Serializer(settings.SECRET_KEY, 3600) # 随机字符串和过期时间要和加密时设置的一样
try:
info = seriaizer.loads(token) # 解密
# 获取激活用户的id
user_id= info["confirm"]
# 根据id获取用户信息
user = User.objects.get(id=user_id)
user.is_active=1
user.save()
# 跳转到登录页面
# return redirect(reverse('user:login')) # 登陆还没定义,后期自己放开
return HttpResponse("登录页")
except SignatureExpired as e:
# 激活链接已过期
return HttpResponse("激活链接已过期")
(2). 定义激活路由
url(r'^active/(?P<token>.*)$',ActiveView.as_view(),name="active"), # 用户激活
三. 发送激活邮件
1. 直接发邮件(不推荐)
可能会造成页面延迟,一直卡在注册页
(1). settings.py配置发件人
# 发送邮件配置
EMAIL_BACKEND='django.core.mail.backends.smtp.EmailBackend',
# smtp服务的邮件服务器
EMAIL_HOST = 'smtp.163.com'
# smtp服务固定的端口是25 / 625
EMAIL_PORT = 25
# 发送邮件的邮箱
EMAIL_HOST_USER = 'a123@163.com'
# 在邮箱中设置的客户端授权密码
EMAIL_HOST_PASSWORD = 'XXXX' # 自行百度查看163邮箱的授权码怎么获取
# 收件人看到的发件人《此处要和发送邮件的邮箱相同>
EMAIL_FROM = 'python<a123@163.com>'
(2). 注册类 发送邮件
#再注册类中发送邮件
from django.core.mail import send_mail
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer, SignatureExpired
from django.conf import settings
class RegisterView(View):
"""注册"""
def get(self, request):
"""显示注册页面"""
...
def post(self, request):
"""进行注册处理"""
# 1. 接收数据
...
# 2. 进行校验
...
# 3. 进行业务处理: 进行用户注册
...
user.save() # 额外 保存
# 加密用户的身份信息,生成激活token
# 加密对象( 随机字符串,过期时间(秒) )
seriaizer = Serializer(settings.SECRET_KEY, 3600)
info = {'confirm': user.id}
token = seriaizer.dumps((info)) # dumps: 加密, bytes类型
token = token.decode() # 解码: 默认utf8
# 发邮件
subject='天天生鲜欢迎信息'
message = ''
sender = settings.EMAIL_FROM # 发件人
receiver = [email] # 收件人
# 包含html内容,需要使用html_message参数进行转义,否则就会当成字符串原样输出
html_message = '<h1>%s, 欢迎您称为天天生鲜注册会员</h1>请点击下面链接激活您的账户<br/><a href="http://127.0.0.1:8000/user/active/%s">http://127.0.0.1:8000/user/active/%s</a>'%(username,token,token)
send_mail(subject,message,sender,receiver,html_message=html_message)
# 4. 返回应答,跳转到首页
...
2. celery异步发邮件(推荐)
(1). 安装第三方库
pip install celery==4.4.7
pip install redis==3.2
(2). 创建异步发邮件文件
# 新建 apps / celery_tasks / tasks.py
# 使用celery
import time
from celery import Celery
# 在任务处理者一端加这几句
# import django
# import os
# # django文件初始化
# os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django20.settings')
# django.setup()
# 启动项目端不需要加这几句
# 创建一个Celery类的实例对象
from django.conf import settings
from django.core.mail import send_mail
# (名字:一般都写路径, broker=中间人)
app = Celery('celery_tasks.tasks',broker='redis://192.168.37.151:6379/8')
# 定义任务函数
@app.task
def send_register_activer_email(to_email,username,token):
"""发送激活邮件"""
# 组织邮件信息
subject = '天天生鲜欢迎信息'
message = ''
sender = settings.EMAIL_FROM # 发件人
receiver = [to_email] # 收件人
# 包含html内容,需要使用html_message参数进行转义,否则就会当成字符串原样输出
html_message = '<h1>%s, 欢迎您称为天天生鲜注册会员</h1>请点击下面链接激活您的账户<br/><a href="http://127.0.0.1:8000/user/active/%s">http://127.0.0.1:8000/user/active/%s</a>' % (
username, token, token)
send_mail(subject, message, sender, receiver, html_message=html_message)
time.sleep(5)
(3). 注册类调用异步文件
from apps.celery_tasks.tasks import send_register_activer_email
class RegisterView(View):
"""注册"""
def get(self, request):
"""显示注册页面"""
...
def post(self, request):
"""进行注册处理"""
# 1. 接收数据
...
# 2. 进行校验
...
# 3. 进行业务处理: 进行用户注册
...
user.save() # 额外 保存
# 加密用户的身份信息,生成激活token
# 加密对象( 随机字符串,过期时间(秒) )
seriaizer = Serializer(settings.SECRET_KEY, 3600)
info = {'confirm': user.id}
token = seriaizer.dumps((info)) # dumps: 加密, bytes类型
token = token.decode() # 解码: 默认utf8
# 异步发邮件
# .delay放到任务队列(函数参数,x,x)
send_register_activer_email.delay(email,username,token)
# 4. 返回应答,跳转到首页
...
(4). 启动任务处理者
中间人redis在 虚拟机(centos7)上,所以在虚拟机启动处理者
处理者也需要项目的代码. 复制一份到 linux 上
如果本地异步文件代码改动, 虚拟机上的文件代码也需要修改
①. 复制项目到虚拟机上
②. 创建虚拟环境- 安装依赖包
# contos 虚拟环境 自行百度搜索
# widows上 生成依赖包文件
pip freeze > requirements.txt
# 虚拟机上下载依赖包
pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple/
# 安装时报错:报错"WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv"
# 解决方案
1. 安装 virtualenv
2. 在那执行,虚拟环境就建在那
virtualenv myproject
3.进入虚拟环境
source myproject/bin/activate
4.在虚拟环境中使用以下命令安装依赖库
pip install -r requirements.txt
5.当您完成时,只需运行以下命令退出虚拟环境
deactivate
③. 虚拟机上异步文件 初始化 django配置文件
④. 进入虚拟机的 项目根目录,启动处理者
# 启动处理者
# celery -A 异步文件名 worker -l info
celery -A apps.celery_tasks.tasks worker -l info
# 报错:AttributeError: 'EntryPoints' object has no attribute 'get'
# 安装以下依赖包:
# pip install frozenlist==1.3.1 geopy==2.2.0 humanize==4.3.0 idna==3.3 importlib-metadata==4.12.0 jsonschema==4.9.0 korean_lunar_calendar==0.2.1 marshmallow==3.17.0 pyOpenSSL==22.0.0 pyrsistent==0.18.1 python-dotenv==0.20.0 pytz==2022.2.1 selenium==4.4.0 simplejson==3.17.6 sniffio==1.2.0 trio==0.21.0 urllib3==1.26.11 wsproto==1.1.0 zipp==3.8.1
# 如果上述安装仍未解决,则执行以下安装,笔者执行完上述安装即能解决问题
# pip install backoff==2.1.2 colorama==0.4.5 croniter==1.3.5 cryptography==37.0.4 email-validator==1.2.1 flask-compress==1.12 flask-migrate==3.1.0 aiohttp==3.8.1 aiosignal==1.2.0 Mako==1.2.1 Babel==2.10.3
⑤. 启动成功样式