zoukankan      html  css  js  c++  java
  • 02 用户注册通过发送邮箱激活

    配置静态文件

    在项目根目录下创建静态文件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数据库中的查询的结果如下:

     

     
     
     
  • 相关阅读:
    Echarts使用笔记
    vue导出pdf
    mvn上传pom/jar至Nexus私服
    Linux下安装Redis
    国内首发,这款 Serverless 云原生一体化部署工具正式开源!
    使用云托管快速部署CMS内容管理系统
    云开发走进高校,腾讯云联合新工科联盟探索新生工程教育模式
    从0到3000万,TA们用云开发这样做
    基于 ThinkJS 的云开发体验
    使用小程序·云开发静态托管实现免鉴权h5跳转小程序
  • 原文地址:https://www.cnblogs.com/aaronthon/p/9347798.html
Copyright © 2011-2022 走看看