码迷,mamicode.com
首页 > 其他好文 > 详细

02 用户注册通过发送邮箱激活

时间:2018-07-21 20:34:36      阅读:340      评论:0      收藏:0      [点我收藏+]

标签:base   ati   异步调用   mode   获取参数   hide   令牌   dtd   sign   

配置静态文件

在项目根目录下创建静态文件static目录,用于放置静态的文件

在settings 文件中定义静态内容

STATIC_URL = /static/
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, static),
]

把静态的文件如css,js,image放入static目录中:

技术分享图片

把当前关于注册用到的模板放到模板文件中,

技术分享图片

在应用users中 views视图定义处理注册的请求函数,返回注册的页面:

类视图:http://python.usyiyi.cn/translate/django_182/topics/class-based-views/intro.html

# 导入类视图,主要给urls
from django.views.generic import View

class RegisterView(View):
    """注册"""
    def get(self, request):
        """对应get请求方式,提供注册页面"""
        return render(request, "register.html", )

在根级urls中配置到应用users的跳转路径

import users.urls

url(r‘^users/‘, include(users.urls, namespace="users")),

在uers.urls.py中配置请求路径

from django.conf.urls import url
from . import views

urlpatterns = [

    url(r‘^register$‘, views.RegisterView.as_view(), name="register"),

]

 在浏览器地址栏中输入:

http://127.0.0.1:8000/users/register

  返回的页面如下所示:

技术分享图片

 

注册页中的html代码如下:

技术分享图片
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>天天生鲜-注册</title>
    <link rel="stylesheet" type="text/css" href="../static/css/reset.css">
    <link rel="stylesheet" type="text/css" href="../static/css/main.css">
    <script type="text/javascript" src="../static/js/jquery-1.12.4.min.js"></script>
    <script type="text/javascript" src="../static/js/register.js"></script>
</head>
<body>
    <div class="register_con">
        <div class="l_con fl">
            <a class="reg_logo"><img src="../static/images/logo02.png"></a>
            <div class="reg_slogan">足不出户  ·  新鲜每一天</div>
            <div class="reg_banner"></div>
        </div>

        <div class="r_con fr">
            <div class="reg_title clearfix">
                <h1>用户注册</h1>
                <a href="#">登录</a>
            </div>
            <div class="reg_form clearfix">
                <form method="post">
                    {% csrf_token %}
                <ul>
                    <li>
                        <label>用户名:</label>
                        <input type="text" name="user_name" id="user_name">
                        <span class="error_tip">提示信息</span>
                    </li>                    
                    <li>
                        <label>密码:</label>
                        <input type="password" name="pwd" id="pwd">
                        <span class="error_tip">提示信息</span>
                    </li>
                    <li>
                        <label>确认密码:</label>
                        <input type="password" name="cpwd" id="cpwd">
                        <span class="error_tip">提示信息</span>
                    </li>
                    <li>
                        <label>邮箱:</label>
                        <input type="text" name="email" id="email">
                        <span class="error_tip">提示信息</span>
                        {{ errmsg }}
                    </li>
                    <li class="agreement">
                        <input type="checkbox" name="allow" id="allow" checked="checked">
                        <label>同意”天天生鲜用户使用协议“</label>
                        <span class="error_tip2">提示信息</span>
                    </li>
                    <li class="reg_sub">
                        <input type="submit" value="注 册" name="">
                    </li>
                </ul>                
                </form>
            </div>

        </div>

    </div>

    <div class="footer no-mp">
        <div class="foot_link">
            <a href="#">关于我们</a>
            <span>|</span>
            <a href="#">联系我们</a>
            <span>|</span>
            <a href="#">招聘人才</a>
            <span>|</span>
            <a href="#">友情链接</a>        
        </div>
        <p>CopyRight © 2016 北京天天生鲜信息技术有限公司 All Rights Reserved</p>
        <p>电话:010-****888    京ICP备*******8号</p>
    </div>
    
</body>
</html>
View Code

 用户提交表单的时候接受发送的post请求,由于表单中action表单的地址没写,所以还在原来的请求地址和视图函数中处理,只不过是post的请求而已,

在视图函数中,添加post请求处理的函数:

技术分享图片
from django.core.urlresolvers import reverse
from django import db
from .models import *
import re


def post(self, request):
        """对应post请求方式,接收处理用户的注册数据"""
        # 接收传入的参数
        user_name = request.POST.get("user_name")
        password = request.POST.get("pwd")
        email = request.POST.get("email")
        allow = request.POST.get("allow")

        # 检验参数的正确性
        if not all([user_name, password, email]):
            # 重定向到注册页面
            return redirect(reverse("users:register"))

        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:
            # django的AbstractUser基类提供的创建用户的方法
            user = User.objects.create_user(user_name, email, password)
        except db.IntegrityError:
            # 如果用户名已存在,则抛出此异常信息
            return render(request, "register.html", {"errmsg": "用户名已存在!"})

        # 将用户的激活状态设置为假
        user.is_active = False
        user.save()

        # 将结果返回给前端
        return redirect(reverse("goods:index"))
View Code

在根基目录的urls中,构造商品应用的请求地址

import goods.urls
urlpatterns = [
   
    url(r^, include(goods.urls, namespace=goods)),
]

 

在商品的views中,构造商品主页的请求函数

from django.shortcuts import render
from django.views.generic import View


class IndexView(View):
    def get(self,request):
        return render(request,‘index.html‘)

在应用goods中的urls中,构造商品主页的请求地址

from django.conf.urls import url
from goods import views

urlpatterns = [
    url(r"^$", views.IndexView.as_view(), name="index"),
]

 

 注册成功在数据库中的查询状态:

技术分享图片

使用celery实现异步调用django的发送邮件的模块,让用户激活自己的账号.

主要思想是,先生成一个唯一的口令用来表示用户,通过django中的(itsdangerous模块),在使用celery服务器实现异步发送邮件.

1 根据用户的ID生成唯一的口令:

在用户模模型类中,创建生成唯一口令的方法:

用户生成注册口令文档 http://itsdangerous.readthedocs.io/en/latest/

技术分享图片
from itsdangerous import TimedJSONWebSignatureSerializer as Serializer


class User(AbstractUser, BaseModel):
    """用户"""
    class Meta:
        db_table = "df_users"

    def generate_active_token(self):
        """生成激活令牌"""
        # 构建序列化器(转换工具)对象
        serializer = Serializer(settings.SECRET_KEY, 3600)
        # 转换参数
        token = serializer.dumps({"confirm": self.id})  # 返回bytes类型
        return token.decode()
View Code

2 在项目根目录下创建celery_tasks的包用来存储用celery发送任务的模块,在包中创建tasks.py模块其内容为:

技术分享图片
from celery import Celery
import os

#把jiango的配置模型放到系统的环境变量中,celery才可以调用django的模块
os.environ["DJANGO_SETTINGS_MODULE"] = "dailyfresh_13.settings"

# 放到celery服务器上时将注释打开
# import django
# django.setup()

from django.core.mail import send_mail
from django.conf import settings

# 创建celery应用对象
app = Celery("celery_tasks.tasks", broker="redis://10.211.55.5/2")


# 定义任务
@app.task
def send_active_email(user_name, to_email, token):
    """发送激活邮件"""
    subject = "天天生鲜用户激活"  # 邮件标题
    body = ""  # 邮件体
    sender = settings.EMAIL_FROM  # 发件人
    receivers = [to_email]  # 接收人
    html_body = <h1>尊敬的用户 %s, 感谢您注册天天生鲜!</h1>                 <br/><p>请点击此链接激活您的帐号<a href="http://127.0.0.1:8000/users/active/%s">                 http://127.0.0.1:8000/users/active/%s<a></p> % (user_name, token, token) # html邮件体
    send_mail(subject, body, sender, receivers, html_message=html_body)
View Code

 3 调用celery任务入到broker队列中,以便刚才我们创建的celery workder服务器能够从队列中取出任务并执行。如何将任务函数加入到队列中,可使用delay()

在用户注册的post请求处理函数中,将发送邮件的任务函数加入到队列中,

把下面的两行代码加到  class RegisterView(View):的post请求函数中

from celery_tasks.tasks import send_active_email

# 为用户生成激活口令
        token = user.generate_active_token()

        # 使用celery异步发送邮件
        send_active_email.delay(user_name, email, token)

  技术分享图片

4 打开项目的settings.py文件,配置Email:

# Email
EMAIL_BACKEND = ‘django.core.mail.backends.smtp.EmailBackend‘
EMAIL_HOST = ‘smtp.126.com‘
EMAIL_PORT = 25
#发送邮件的邮箱
EMAIL_HOST_USER = ‘daily_fresh@126.com‘
#在邮箱中设置的客户端授权密码
EMAIL_HOST_PASSWORD = ‘ITCAST123‘
#收件人看到的发件人
EMAIL_FROM = ‘天天生鲜<daily_fresh@126.com>‘

5 处理用户激活的请求:

  定义用户激活的请求的处理函数:

# 口令过期
from itsdangerous import SignatureExpired

# 定义了激活的接口
class ActiveView(View):
    """激活"""
    def get(self, request, token):
        """

        :param request:
        :param token: token是用户携带的口令,唯一标识用户
        :return:
        """
        # 解析口令token,获取用户身份
        # 构建序列化器
        s = Serializer(settings.SECRET_KEY)
        try:
            data = s.loads(token)
        except SignatureExpired:
            # 表示token过期
            return HttpResponse("链接已过期!")
        # 表示token未过期,
        user_id = data.get("confirm")

        # 查询用户的数据.处理bug
        try:
            user = User.objects.get(id=user_id)
        except User.DoesNotExist:
            # 用户不存在
            return HttpResponse("用户不存在!")
        # 设置用户的激活状态
        user.is_active = True
        user.save()

        # 返回处理结果
        return HttpResponse("ok")
        # return redirect(reverse("users:login"))    

 

6 配置用户激活请求的url:

 url(r‘^active/(?P<token>.+)‘, views.ActiveView.as_view(), name="active"),

5 .打开终端,执行命令:

celery -A celery_tasks.tasks worker --loglevel=info

技术分享图片

用户dsa提交表单:

技术分享图片

celery发送邮件成功:

技术分享图片

用户dsa接受到邮件点击激活后,查询数据库中的is_active的状态为1,激活成功:

技术分享图片

 定义用户登陆请求的处理函数:

 Django认证系统文档  http://python.usyiyi.cn/documents/django_182/topics/auth/default.html

from django.contrib.auth import authenticate, login


class LoginView(View):
    """登录"""
    def get(self, request):
        """提供登录页面"""
        return render(request, "login.html")

    def post(self, request):
        """处理登录的数据"""
        # 获取参数
        user_name = request.POST.get("username")
        password = request.POST.get("pwd")

        # 参数校验
        if not all([user_name, password]):
            # 参数不完整
            return render(request, "login.html")

        # 登录业务逻辑处理
        # try:
        #     password = sha256(password)
        #     User.objects.get(username=user_name, password=password)
        # except User.DoesNotExist:
        #     return HttpResponse("用户名或密码错误")

        # 使用django的认证系统进行用户密码的校验
        user = authenticate(username=user_name, password=password)
        if user is None:
            # 用户的登录信息有误
            return render(request, "login.html", {"errmsg": "用户名或密码错误!"})

        # 判断用户的激活状态
        if user.is_active is False:
            return render(request, "login.html", {"errmsg": "用户尚未激活!"})

        # 保存用户的登录状态
        # 使用django的login函数保存用户的session数据
        login(request, user)

        # 登录成功,跳转到主页
        return HttpResponse(‘登陆成功‘)
        #return redirect(reverse("goods:index"))

在浏览器输入以下的网址:

http://127.0.0.1:8000/users/login

  技术分享图片

用户和激活的状态判断成功后,显示以下的页面:

技术分享图片 

 配置用户登陆请求的url:

 url(r‘^login$‘, views.LoginView.as_view(), name="login"),

 

======================================================================================================

用户登陆成功,返回主页的请求处理函数,这个请求处理函数写在goods应用中的views函数中:

技术分享图片

from django.shortcuts import render
from django.views.generic import View

# Create your views here.


class IndexView(View):
    """主页"""
    def get(self, request):
        return render(request, "index.html")

 

定义用户登陆主页的请求路径:

现在根据的请求路径urls中,定义再跳到goods应用中的urls

在根基定义跳转的路径:

url(r‘^/‘, include(goods.urls, namespace="goods")),

在goods应用中的urls模块中写请求登陆主页的路径:

from django.conf.urls import url
from goods import views

urlpatterns = [
    url(r"^$", views.IndexView.as_view(), name="index"),
]

 在用户登陆处理函数login中把最后的登陆成功的路径跳转到主页

  # return HttpResponse(‘登陆成功‘)
 return redirect(reverse(‘goods:index‘))

  技术分享图片

点击登陆,认证成功后,返回以下的页面:

技术分享图片

============================================================

把session和缓存储在redis数据库中,在setings中配置代码以下:

pip install django-redis

 django-redis文档:http://django-redis-chs.readthedocs.io/zh_CN/latest/#

django的session使用文档:http://python.usyiyi.cn/documents/django_182/topics/http/sessions.html

CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://localhost/3",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    }
}


# Session
# http://django-redis-chs.readthedocs.io/zh_CN/latest/#session-backend

SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"

 用户登陆成功后,在redis数据库中的查询的结果如下:

技术分享图片 

 

02 用户注册通过发送邮箱激活

标签:base   ati   异步调用   mode   获取参数   hide   令牌   dtd   sign   

原文地址:https://www.cnblogs.com/aaronthon/p/9347798.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!