美文网首页零基础使用Django2.0.1打造在线教育网站
零基础使用Django2.0.1打造在线教育网站(十四):用户密

零基础使用Django2.0.1打造在线教育网站(十四):用户密

作者: 啃饼小白 | 来源:发表于2018-08-04 08:11 被阅读4次

    写在前面

    本篇笔记我们将实现用户的激活,用户密码找回,重置密码,修改密码等功能,前面所介绍的知识大家没事可以复习一下,加深对知识的理解和应用,后面很多东西就是前面讲过的知识的应用。

    本篇笔记对应于第十四篇代码,对应于github的位置是https://github.com/licheetools/eduline

    用户激活的操作

    打开我们的Navicat,去数据库中找到我们的用户信息表:


    这里面有个字段is_active,它是用来判别用户是否激活的,默认是未激活也就是0,这里都是1肯定是不行的,所以我们需要定义激活用户的函数,来完成用户的激活操作。

    先配置一下路径path,打开eduline/urls.py文件,在里面添加一行代码:

    from django.urls import  re_path
    from users.views import ActiveUserView  #ActiveUserView目前未定义,后面马上定义
    
    
    # 激活用户url
    re_path('active/(?P<active_code>.*)/', ActiveUserView.as_view(), name="user_active")
    

    'active/(?P<active_code>.*)/'是正则表达式模式,用于匹配验证码!

    打开users/views.py文件,我们设置默认未激活:

    # 默认激活状态为False,也就是未激活
    user_profile.is_active = False
    

    并且在下面新增代码:

    from .models import EmailVerifyRecord
    
    # 用于实现用户激活操作的函数
    class ActiveUserView(View):
        def get(self, request, active_code):
            # 用于查询邮箱验证码是否存在
            all_record = EmailVerifyRecord.objects.filter(code=active_code)
     
            if all_record:
                for record in all_record:
                    # 获取到对应的邮箱
                    email = record.email
                    # 查找到邮箱对应的用户
                    user = UserProfile.objects.filter(email=email)
                    user.is_active = True #激活用户
                    user.save()
                    # 激活成功跳转到登录页面
                return render(request, "login.html")
    

    现在回到我们的LoginView函数,我们当时没有判断用户是否激活,现在需要判断,修改代码如下:

     if user is not None:
                    if user.is_active:
                        # login 有两个参数:request和user。我们在请求的时候,request实际上是写进了一部分信息,然后在render的时候,这些信息也被返回前端页面从而完成用户登录
                        login(request, user)
                        # 页面跳转至网站首页 user request也会被带回到首页,显示登录状态
                        return render(request, "index.html")
                    else:
                        return render(request, "login.html", {'msg': '用户未激活!'})
                else:
                    # 说明里面的值是None,再次跳转回主页面并报错,这里仅当用户密码出错时才返回
                    return render(request, "login.html", {'msg': '用户名或者密码错误!'})
    

    将数据表中的licheetools@sina.cn 用户的is_active修改为0,我们来测试一下,在图中所示位置打上断点,开始调试:
    我们的用户测试激活调试没有问题,再来看一下验证码激活:我们去新浪邮箱,将获取到的链接访问一下:
    请点击下面的链接激活你的账号: http://127.0.0.1:8000/active/HekaM6EfZfeKy1Zc
    

    按图示来测试一下,也没有问题!

    至此,我们完成了邮箱验证码的激活以及用户的激活。

    不过我们还有两个问题,一个就是前面没有判断邮箱是否已经存在,我们不能用旧的邮箱来注册,所以我们需要配置一下,打开users/views.py文件,修改代码如下:

        def post(self, request):
            # 类的实例化需要一个字典dict参数,而前面我们就知道request.POST是一个QueryDict,所以可以直接传入POST中的信息
            register_form = RegisterForm(request.POST)
            if register_form.is_valid():
                user_name = request.POST.get("email", "")
                if UserProfile.objects.filter(email=user_name):
                    # register_form回填信息必须有,msg是信息提示
                    return render(request, 'register.html', {'register_form': register_form}, {'msg': '该邮箱已被注册过了'})
                else:
                    # password为前端页面name的返回值,取到用户名和密码我们就开始进行登录验证;取不到时为空。
                    pass_word = request.POST.get("password", "")
                    # 实例化一个user_profile对象,存入前端页面获取的值
                    user_profile = UserProfile()
                    user_profile.username = user_name
                    user_profile.email = user_name
    
                    # 默认激活状态为False,也就是未激活
                    user_profile.is_active = False
    
                    # 对password进行加密并保存
                    user_profile.password = make_password(pass_word)
                    user_profile.save()
                    send_register_eamil(user_name, 'register')
                    pass
    

    另一个就是我们对于链接的处理不够完善,正如你所了解的那样,链接肯定有有效时间,在这个规定的时间内点击才有用,过了规定时间就没有用,所以我们需要新建一个链接超时的html文件:新建active_fail.html文件,里面就几行代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>链接失效</title>
    </head>
    <body>
    <p>对不起,链接失效了</p>
    </body>
    </html>
    

    然后我们来users/views.py文件,修改一下激活的代码:

    # 用于实现用户激活操作的函数
    class ActiveUserView(View):
        def get(self, request, active_code):
            # 用于查询邮箱验证码是否存在
            all_record = EmailVerifyRecord.objects.filter(code=active_code)
            if all_record:
                for record in all_record:
                    # 获取到对应的邮箱
                    email = record.email
                    # 查找到邮箱对应的用户
                    user = UserProfile.objects.filter(email=email)
                    user.is_active = True
                    user.save()
            else:
                return render(request, "active_fail.html")
            # 激活成功跳转到登录页面
            return render(request, "login.html")
    
    按照图示打上断点并开始调试:

    调试没有问题!

    好,解决了上面两个问题之后,下面我们来进行忘记密码,找回密码的操作。

    忘记密码的操作

    拷贝forgetpwd页面

    forgetpwd.html页面拷贝到我们的templates文件夹里面:

    定义(忘记)找回密码的视图

    打开users/views.py文件,在里面添加如下代码:

    # 用于实现用户忘记码(找回密码)的函数
    class ForgetPwdView(View):
        def get(self, request):
            return render(request, "forgetpwd.html", {})
    

    然后在eduline/urls.py文件里面配置url信息:

    from users.views import  ForgetPwdView
    
    # 找回密码url,注意是普通的url
    path("forget/", ForgetPwdView.as_view(), name="forget_pwd"),
    

    接下来配置跳转路径,首先ctrl+F 搜索login.html,找到忘记密码,修改href属性:

    <a class="fr" href="forgetpwd.html">忘记密码?</a>
    

    修改为:

     <a class="fr" href="{% url 'forget_pwd' %}">忘记密码?</a>
    

    注意外部有双引号,里面就只能使用单引号。

    接着继续修改forgetpwd.html页面的跳转链接,一样的操作,这里就不演示了!

    现在运行一下我们的项目,在浏览器地址栏中输入:http://127.0.0.1:8000/forget/,出现了:


    样式没有加载出来,我们需要和前面的一样,加上静态相对路径,忘记的小伙伴可以查看第十一篇笔记:零基础使用Django2.0.1打造在线教育网站(十一):登录页面实现
    1、页面第三行加上{% load staticfiles %}
    2、修改全部类型文件的static相对路径
    3、修改其中的url,配置跳转链接
    

    配置完刷新一下页面:

    这个页面其实也是一个表单,所以需要定义form表单,我们可以仿照注册的表单来书写,打开我们的users/forms.py文件,在里面添加一下代码:

    # 用户找回密码时的表单,注意字段与前端页面保持一致
    class ForgetForm(forms.Form):
        email = forms.CharField(required=True)  # 用户名不能为空
        captcha = CaptchaField(error_messages={"invalid": "验证码错误"})
    

    接着回到我们的views.py文件,继续完善ForgetPwdView:

    from users.forms import  ForgetForm
    
    # 用于实现用户忘记码(找回密码)的函数
    class ForgetPwdView(View):
        def get(self, request):
            forget_form = ForgetForm()
            return render(request, "forgetpwd.html", {'forget_form': forget_form})
    
    
    然后回到我们的forgetpwd.html页面,我们删除captcha那一行,并修改为:
    <div class="form-group captcha1 marb38">
                            <label>验&nbsp;证&nbsp;码</label>
                            {{ forget_form.captcha }}
     </div>
    
    我们再来刷新一下我们的页面:

    页面正常显示了!

    既然我们是找回密码,那么我们肯定需要发送邮件,我们前面新建了发送失败的html页面,那我们肯定也需要新建一个发送成功的html页面吧,新建send_success.html文件:


    里面添加如下代码:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>邮件发送成功</title>
    </head>
    <body>
    <p>邮件已发送,请注意查收!</p>
    </body>
    </html>
    

    还是回到我们的views.py文件,继续完善ForgetPwdView的post方法:

    # 用于实现用户忘记码(找回密码)的函数
    class ForgetPwdView(View):
        def get(self, request):
            forget_form = ForgetForm()
            return render(request, "forgetpwd.html", {'forget_form': forget_form})
    
        def post(self, request):
            forget_form = ForgetForm(request.POST)
            if forget_form.is_valid():
                email = request.POST.get('email', '')
                # 发送找回密码的邮件
                send_register_eamil(email, 'forget')
                return render(request, 'send_success.html')
            else:
                return render(request, "forgetpwd.html", {'forget_form': forget_form})
    
    再回到前端页面,看看这些是不是都修改完了:
    还有页面的提示信息也要修改(参考前面的介绍):

    至此,我们密码找回就已经完成了,我们来测试一下:




    测试成功了!

    下面完成重置密码和修改密码的操作!

    重置密码的操作

    拷贝password_reset.html页面

    password_reset.html页面拷贝到我们的templates文件夹里面:

    定义重置密码的视图

    打开users/views.py文件,在里面添加如下代码:

    # 用于实现用户重置密码的函数
    class ResetView(View):
        def get(self, request, active_code):
            # 用于查询邮箱验证码是否存在
            all_record = EmailVerifyRecord.objects.filter(code=active_code)
            if all_record:
                for record in all_record:
                    # 获取到对应的邮箱
                    email = record.email
                    # 查找到邮箱对应的用户
                    return render(request, "password_reset.html", {"email": email})   # 告诉页面是哪个用户在重置密码
            else:
                return render(request, "active_fail.html")
            # 激活成功跳转到登录页面
            return render(request, "login.html")
    

    然后在eduline/urls.py文件里面配置url信息:

    from users.views import  ResetView
    
     # 密码重置url
        re_path('reset/(?P<active_code>.*)/', ResetView.as_view(), name="reset_pwd"),
    

    接下来我们在页面隐式回填刚才的email,在password_reset.html页面,添加下面一行代码:

     <input type="hidden" name="email" value="{{ email }}">
    
    就是这个样子: 现在调试一下我们的项目,在图示位置打上断点:

    接着我们登录新浪邮箱(前面是QQ邮箱就用QQ邮箱),查找我们的之前的重置密码邮件:


    接着将重置密码链接复制到浏览器地址栏打开,页面进入到Pycharm出现了: 然后step out结束: 还记得我们刚才在里面加的那个input么,它的作用是告知页面哪个用户此时此刻正在重置密码,我们点击查看网页源代码,看是不是input起了作用:

    看到没有,确实起了作用,不过我们除非查看了源码,否则是看不到的!

    不过样式没有加载出来,我们需要和前面的一样,加上静态相对路径,忘记的小伙伴可以查看第十一篇笔记:零基础使用Django2.0.1打造在线教育网站(十一):登录页面实现

    1、页面第三行加上{% load staticfiles %}
    2、修改全部类型文件的static相对路径
    3、修改其中的url,配置跳转链接
    

    配置完以后我们刷新页面会出错,这是正常现象,因为我们在url跳转时缺少参数,这个先放在这里(如果你为了不影响心情,可以不刷新页面)!

    刚才那个页面其实也是一个表单,所以需要定义form表单,我们可以仿照注册的表单来书写,打开我们的users/forms.py文件,在里面添加一下代码:

    # 用户修改密码时的表单,注意字段与前端页面保持一致
    class ModifyPwdForm(forms.Form):
        password1 = forms.CharField(required=True, min_length=5)  # 新密码不能为空
        password2 = forms.CharField(required=True, min_length=5)  # 确认密码不能为空
    
    记得与前端页面字段一致:

    接着回到我们的views.py文件,继续完善ResetView:

    from users.forms import  ModifyPwdForm
    
        def post(self, request):
            modify_form = ModifyPwdForm(request.POST)
            if modify_form.is_valid():
                pwd1 = request.POST.get("password1", '')
                pwd2 = request.POST.get("password2", '')
                email = request.POST.get("email", '')
                # 如果前后两次密码不相等,那么回填信息并返回错误提示
                if pwd1 != pwd2:
                    return render(request, "password_reset.html", {"email": email, "msg": "对不起,前后密码不一致"})
                # 如果前后两次密码相等,那么进入我们的密码修改保存
                # 取出用户信息
                user = UserProfile.objects.get(email=email)
                # 随意取出一个密码并将其进行加密
                user.password = make_password(pwd1)
                # 将更新后的用户信息保存到数据库里面
                user.save()
                # 密码重置成功以后,跳转到登录页面
                return render(request, "login.html", {"msg": "恭喜您,您的密码修改成功,请登录"})
            else:
                email = request.POST.get("email", '')
                return render(request, "password_reset.html", {"email": email, "modify_form": modify_form})
    
    

    我们现在来解决刚才url出错的问题,我们在path中的配置是这样的:

    re_path('reset/(?P<active_code>.*)/', ResetView.as_view(), name="reset_pwd"),
    

    它和我们普通的path不一样,里面有一个匹配active_code的正则表达式,所以在前端页面不能和普通的url那样写:

     action="{% url 'reset_pwd' %}"
    

    既然不能这样写,那我们可以用一个普通的path来定义它,作用是修改密码即可:

    from users.views import  ModifyPwdView
    
    # 修改密码url
    path("modify/", ModifyPwdView.as_view(), name="modify_pwd"),
    

    这里面的ModifyPwdView是我们新建的视图函数,可以将前面的ResetView中的post方法脱离出来,成为ModifyPwdView的一部分:

    # 用于实现用户修改密码的函数
    class ModifyPwdView(View):
        def post(self, request):
            modify_form = ModifyPwdForm(request.POST)
            if modify_form.is_valid():
                pwd1 = request.POST.get("password1", '')
                pwd2 = request.POST.get("password2", '')
                email = request.POST.get("email", '')
                # 如果前后两次密码不相等,那么回填信息并返回错误提示
                if pwd1 != pwd2:
                    return render(request, "password_reset.html", {"email": email, "msg": "对不起,前后密码不一致"})
                # 如果前后两次密码相等,那么进入我们的密码修改保存
                # 取出用户信息
                user = UserProfile.objects.get(email=email)
                # 随意取出一个密码并将其进行加密
                user.password = make_password(pwd1)
                # 将更新后的用户信息保存到数据库里面
                user.save()
                # 密码重置成功以后,跳转到登录页面
                return render(request, "login.html", {"msg": "恭喜您,您的密码修改成功,请登录"})
            else:
                email = request.POST.get("email", '')
                return render(request, "password_reset.html", {"email": email, "modify_form": modify_form})
    
    
    也就是这个样子:

    然后修改前端页面:

    <form id="reset_password_form" action="{% url 'modify_pwd' %}" method="post">
    
    也就是这个样子: 在图示位置打上断点,开始调试我们的项目,具体操作和前面类似,这里就不介绍了。

    复制密码重置链接去浏览器地址栏打开,输入新的密码:


    然后点击提交按钮,就进入下面的Pycharm页面:

    注意:如果点击提交按钮没有反应,页面没有进入view.py里面的方法,可能是按钮的类型错了,type="submit"而不是type="button",也就是这个样子:

    最后,修改password_reset.html的错误信息的提示:

    前面说了这么多调试命令,小伙伴们可能会不太明白其中的意思,下面我详细介绍一下Pycharm是如何调试代码的!

    Pycharm中的调试

    如果你熟悉Eclipse,那你肯定知道它的快捷键:

    F5:跳入方法
    F6:向下逐行调试
    F7:跳出方法
    F8:直接跳转到下一个断点
    

    当然Pycharm也是可以采用Eclipse的快捷键来调试代码的,具体设置方法如下:

    点击File--> Settings--> Apperance--> Keymap--> 右侧下拉选Eclipse--> Apply --> OK这几步就完成了,没看懂的可以看下面的图片(记得按照序号的顺序来操作哈)

    当然如果你没用过Eclipse,也不想记那些快捷键,这也是可以的,那看下面的图片:

    这个页面你总是经常看到吧,下面分别解释一下各个键的名称及功能作用(括号内是默认的快捷键,也就是Pycharm自己设定的):


    • 1、step over(F8)作用是在同一个调用栈层中移动到下一个可执行的代码行。如果当前行是一个函数调用,则调试器将在函数调用之后的下一条语句停止。调试器不会进入函数体。如果当前行是函数的最后一行,则step-over将进入下一个栈层,并在调用函数的下一行停止。


    • 2、step into(F7)作用是移动到下一个可执行的代码行。如果当前行是一个函数调用,则调试器将进入函数,并停止在函数体的第一行。step-into可以帮助初步揭开代码位置的谜团。例如,函数调用和函数本身可能在不同的文件中是函数的最后一行,则step-over将进入下一个栈层,并在调用函数的下一行停止。


    • 3、Force step into(Ctrl+shift+F7)可以看做是step into的升级版本,可以越过代码,强力执行。


    • 4、step-out(shift+F8)作用是在栈中前进到下一层,并在调用函数的下一行停止。

    还有,如果你有多个断点,如何在pycharm中从第一个断点跳转至第二个断点呢?
    例如第一个断点在第一行,第二个断点在第五十行,那么开始debug后,你首先停在第一行,随后点击菜单栏的Run-> Resume Program即可跳转至第二个断点了,是不是很简单!

    至此,关于用户的激活,用户密码找回,重置密码,修改密码,调试代码等功能的介绍就到此为止,感谢你的赏阅!

    本篇笔记对应于第十四篇代码,对应于github的位置是https://github.com/licheetools/eduline

    相关文章

      网友评论

        本文标题:零基础使用Django2.0.1打造在线教育网站(十四):用户密

        本文链接:https://www.haomeiwen.com/subject/wtnlvftx.html