完成登录 注册 找回密码 激活 验证码集成

将HTML文件拷贝到templates目录下,css,js,img,media,images文件夹拷贝到static文件夹下

修改index.html和login.html文件中的静态文件路径,全部替换为如下格式

  1. <link rel="stylesheet" type="text/css" href="{% static "css/reset.css" %}">
  2. <link rel="stylesheet" type="text/css" href="{% static "css/animate.css" %}">
  3. <link rel="stylesheet" type="text/css" href="{% static "css/style.css" %}">

在文件最上方加入

  1. {% load staticfiles %}

配置主页面的路由

  1. urlpatterns = [
  2. path('admin/', xadmin.site.urls),
  3. path('',TemplateView.as_view(template_name='index.html'), name='index'),
  4. ]

配置登陆页面的路由

  1. path('login/',LoginView.as_view(),name = 'login'),

编写登陆的逻辑代码

users/views.py

  1. # 实现用户名邮箱均可登录
  2. # 继承ModelBackend类,因为它有方法authenticate,可点进源码查看
  3. from users.models import UserProfile
  4. class CustomBackend(ModelBackend):
  5. def authenticate(self, username=None, password=None, **kwargs):
  6. try:
  7. # 不希望用户存在两个,get只能有一个。两个是get失败的一种原因 Q为使用并集查询
  8. user = UserProfile.objects.get(Q(username=username)|Q(email=username))
  9. # django的后台中密码加密:所以不能password==password
  10. # UserProfile继承的AbstractUser中有def check_password(self, raw_password):
  11. if user.check_password(password):
  12. return user
  13. except Exception as e:
  14. return None
  15. class LoginView(View):
  16. def get(self,request):
  17. return render(request, 'login.html')
  18. def post(self,request):
  19. # 获取用户提交的用户名和密码
  20. user_name = request.POST.get('username', None)
  21. pass_word = request.POST.get('password', None)
  22. # 成功返回user对象,失败None
  23. user = authenticate(username=user_name, password=pass_word)
  24. # 如果不是null说明验证成功
  25. if user is not None:
  26. # 登录
  27. login(request, user)
  28. return render(request, 'index.html')
  29. else:
  30. return render(request, 'login.html', {'msg': '用户名或密码错误'})

settings.py中启用自定义验证

  1. # 自定义登陆验证
  2. AUTHENTICATION_BACKENDS = (
  3. 'users.views.CustomBackend',
  4. )

修改login文件中的form表单

访问http://127.0.0.1:8000/login/即可进行登陆,成功会跳转到主页面,失败则会显示错误信息

form实现登陆

users目录下新建一个forms.py的文件

  1. from django import forms
  2. # 登录表单验证
  3. class LoginForm(forms.Form):
  4. # 用户名密码不能为空
  5. username = forms.CharField(required=True)
  6. password = forms.CharField(required=True, min_length=6)

修改LoginView的内容

  1. def post(self, request):
  2. # 类实例化需要一个字典参数dict:request.POST就是一个QueryDict所以直接传入
  3. # POST中的username,password,会对应到form中
  4. login_form = LoginForm(request.POST)
  5. # is_valid判断我们字段是否有错执行我们原有逻辑,验证失败跳回login页面
  6. if login_form.is_valid():
  7. # 取不到时为空,username,password为前端页面name值
  8. user_name = request.POST.get("username", "")
  9. pass_word = request.POST.get("password", "")
  10. # 成功返回user对象,失败返回null
  11. user = authenticate(username=user_name, password=pass_word)
  12. # 如果不是null说明验证成功
  13. if user is not None:
  14. # 账号是否激活
  15. if user.is_active:
  16. # login 两参数:request, user
  17. # 实际是对request写了一部分东西进去,然后在render的时候:
  18. # request是要render回去的。这些信息也就随着返回浏览器。完成登录
  19. login(request, user)
  20. # 跳转到首页 user request会被带回到首页
  21. return render(request, "index.html")
  22. else:
  23. return render(request, "login.html", {"msg": "用户未激活!"})
  24. # 验证不成功跳回登录页面
  25. # 没有成功说明里面的值是None,并再次跳转回主页面
  26. else:
  27. return render(request, "login.html", {"msg": "用户名或密码错误! "})
  28. # form.is_valid()已经判断不合法了,所以这里不需要再返回错误信息到前端了,错误信息包含在form.errors中
  29. else:
  30. return render(request,'login.html',{'login_form':login_form})

修改login.html文件内容

  1. <div class="form-group marb20 {% if login_form.errors.username %}errorput{% endif %}">
  2. <label>用&nbsp;户&nbsp;名</label>
  3. <input name="username" id="account_l" type="text" placeholder="手机号/邮箱" />
  4. </div>
  5. <div class="form-group marb8 {% if login_form.errors.username %}errorput{% endif %}">
  6. <label>密&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;码</label>
  7. <input name="password" id="password_l" type="password" placeholder="请输入您的密码" />
  8. </div>
  9. <div class="error btns login-form-tips" id="jsLoginTips">
  10. {% for key,error in login_form.errors.items %}
  11. {{ error }}
  12. {% endfor %}
  13. {{ msg }}
  14. </div>

使用admin账号进行登陆测试


邮箱注册

注册时需要验证码

这里使用插件 django-simple-captcha

  1. pip install django-simple-captcha

配置到INSTALLED_APPS

  1. INSTALLED_APPS = [
  2. ...,
  3. 'captcha',
  4. ]

配置路由

  1. path('captcha/',include('captcha.urls')),

映射到数据库

  1. python manage.py makemigrations
  2. python manage.py migrate

创建一个注册的form

  1. # 引入验证码field
  2. from captcha.fields import CaptchaField
  3. # 验证码form & 注册表单form
  4. class RegisterForm(forms.Form):
  5. # 此处email与前端name需保持一致。
  6. email = forms.EmailField(required=True)
  7. # 密码不能小于5位
  8. password = forms.CharField(required=True, min_length=5)
  9. # 应用验证码
  10. captcha = CaptchaField(error_messages={'invalid': '验证码错误'})

编写注册的逻辑代码

  1. class RegisterView(View):
  2. '''用户注册'''
  3. def get(self,request):
  4. register_form = RegisterForm()
  5. return render(request,'register.html',{'register_form':register_form})
  6. def post(self,request):
  7. register_form = RegisterForm(request.POST)
  8. if register_form.is_valid():
  9. user_name = request.POST.get('email', None)
  10. # 如果用户已存在,则提示错误信息
  11. if UserProfile.objects.filter(email = user_name):
  12. return render(request, 'register.html', {'register_form':register_form,'msg': '用户已存在'})
  13. pass_word = request.POST.get('password', None)
  14. # 实例化一个user_profile对象
  15. user_profile = UserProfile()
  16. user_profile.username = user_name
  17. user_profile.email = user_name
  18. user_profile.is_active = False
  19. # 对保存到数据库的密码加密
  20. user_profile.password = make_password(pass_word)
  21. user_profile.save()
  22. send_register_eamil(user_name,'register')
  23. return render(request,'login.html',{"msg":"邮件已发送,进入邮箱激活"})
  24. else:
  25. return render(request,'register.html',{'register_form':register_form})

修改register.html文件

首先修改静态文件路径,接着修改表单配置


  1. <form id="email_register_form" method="post" action="/register/" autocomplete="off">
  2. <div class="form-group marb20 {% if register_form.errors.email %}errorput{% endif %}">
  3. <label>邮&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;箱</label>
  4. <input type="text" id="id_email" name="email" value="{{ register_form.email.value|default:"" }}" placeholder="请输入您的邮箱地址" />
  5. </div>
  6. <div class="form-group marb8 {% if register_form.errors.password %}errorput{% endif %}">
  7. <label>密&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;码</label>
  8. <input type="password" id="id_password" name="password" placeholder="请输入6-20位非中文字符密码" />
  9. </div>
  10. <div class="form-group marb8 captcha1 {% if register_form.errors.captcha %}errorput{% endif %}">
  11. <label>验&nbsp;证&nbsp;码</label>
  12. {{ register_form.captcha }}
  13. </div>
  14. <div class="error btns" id="jsEmailTips">
  15. {% for key,error in register_form.errors.items %}
  16. {{ error }}
  17. {% endfor %}
  18. {{ msg }}
  19. </div>
  20. <div class="auto-box marb8">
  21. </div>
  22. <input class="btn btn-green" id="jsEmailRegBtn" type="submit" value="注册并登录" />
  23. {% csrf_token %}
  24. </form>

刷新验证码

刷新验证码的功能是前端完成的

  1. //刷新验证码
  2. function refresh_captcha(event){
  3. $.get("/captcha/refresh/?"+Math.random(), function(result){
  4. $('#'+event.data.form_id+' .captcha').attr("src",result.image_url);
  5. $('#id_captcha_0').attr("value",result.key);
  6. });
  7. return false;
  8. }

发送邮件

这里使用新浪邮箱,首先注册一个新浪邮箱,开启SMTP服务

在apps目录下新建一个utils包,在这个包里面新建一个email_send.py文件

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # @Time : 2018/9/7 下午 08:24
  4. # @Author : gao
  5. # @File : email_send.py
  6. from random import Random
  7. from django.core.mail import send_mail
  8. from MxOnline.settings import EMAIL_FROM
  9. from users.models import EmailVerifyRecord
  10. # 生成随机字符串
  11. def random_str(random_length=8):
  12. str = ''
  13. # 生成字符串的可选字符串
  14. chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789'
  15. length = len(chars) - 1
  16. random = Random()
  17. for i in range(random_length):
  18. str += chars[random.randint(0, length)]
  19. return str
  20. # 发送注册邮件
  21. def send_register_eamil(email, send_type="register"):
  22. # 发送之前先保存到数据库,到时候查询链接是否存在
  23. # 实例化一个EmailVerifyRecord对象
  24. email_record = EmailVerifyRecord()
  25. # 生成随机的code放入链接
  26. code = random_str(16)
  27. email_record.code = code
  28. email_record.email = email
  29. email_record.send_type = send_type
  30. email_record.save()
  31. # 定义邮件内容:
  32. email_title = ""
  33. email_body = ""
  34. if send_type == "register":
  35. email_title = "慕课在线 注册激活链接"
  36. email_body = "请点击下面的链接激活你的账号: http://127.0.0.1:8000/active/{0}".format(code)
  37. # 使用Django内置函数完成邮件发送。四个参数:主题,邮件内容,发件人邮箱地址,收件人(是一个字符串列表)
  38. send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
  39. # 如果发送成功
  40. if send_status:
  41. pass
  42. if send_type == "forget":
  43. email_title = "慕课在线 找回密码链接"
  44. email_body = "请点击下面的链接找回你的密码: http://127.0.0.1:8000/reset/{0}".format(code)
  45. # 使用Django内置函数完成邮件发送。四个参数:主题,邮件内容,从哪里发,接受者list
  46. send_status = send_mail(email_title, email_body, EMAIL_FROM, [email])
  47. # 如果发送成功
  48. if send_status:
  49. pass

邮箱激活

  1. # 激活用户的view
  2. class ActiveUserView(View):
  3. def get(self, request, active_code):
  4. # 查询邮箱验证记录是否存在
  5. all_record = EmailVerifyRecord.objects.filter(code = active_code)
  6. # 如果不为空也就是有用户
  7. if all_record:
  8. for record in all_record:
  9. # 获取到对应的邮箱
  10. email = record.email
  11. # 查找到邮箱对应的user
  12. user = UserProfile.objects.get(email=email)
  13. user.is_active = True
  14. user.save()
  15. # 激活成功跳转到登录页面
  16. return render(request, "login.html", )
  17. # 自己瞎输的验证码
  18. else:
  19. return render(request, "active_fail.html")

在templates目录下创建 active_fail.html,代码如下:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <p style="color: red;">链接失效</p>
  9. </body>
  10. </html>

添加激活邮箱的路由

  1. re_path('active/(?P<active_code>.*)/',ActiveUserView.as_view(),name='user_active'),

忘记密码

点击忘记密码,跳转到忘记密码界面,输入邮箱和验证码后给该邮箱发送重置密码链接

邮箱收到链接后,点击链接跳转到重置密码界面,输入新密码点击提交,成功后跳转到登陆界面

路由设置

  1. path('forget/',ForgetPwdView.as_view(),name='forget_pwd'),

新建一个form

  1. class ForgetPwdForm(forms.Form):
  2. '''忘记密码'''
  3. email = forms.EmailField(required=True)
  4. captcha = CaptchaField(error_messages={'invalid': '验证码错误'})

逻辑代码

  1. class ForgetPwdView(View):
  2. '''找回密码'''
  3. def get(self,request):
  4. forget_form = ForgetPwdForm()
  5. return render(request,'forgetpwd.html',{'forget_form':forget_form})
  6. # post方法实现
  7. def post(self, request):
  8. forget_form = ForgetPwdForm(request.POST)
  9. # form验证合法情况下取出email
  10. if forget_form.is_valid():
  11. email = request.POST.get("email", "")
  12. # 发送找回密码邮件
  13. send_register_eamil(email, "forget")
  14. # 发送完毕返回登录页面并显示发送邮件成功。
  15. return render(request, "login.html", {"msg": "重置密码邮件已发送,请注意查收"})
  16. # 如果表单验证失败也就是他验证码输错等。
  17. else:
  18. return render(request, "forgetpwd.html", {"forget_from": forget_form})

修改forgetpwd.html表单提交内容

  1. <form id="jsFindPwdForm" method="post" action="/forget/" autocomplete="off">
  2. <div class="form-group marb20 ">
  3. <label>帐&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;号</label>
  4. <input type="text" id="account" name="email" placeholder="邮箱" />
  5. </div>
  6. <div class="form-group captcha1 marb38">
  7. <label>验&nbsp;证&nbsp;码</label>
  8. {{ forget_form.captcha }}
  9. </div>
  10. <div class="error btns" id="jsForgetTips">
  11. {% for key,error in forget_from.errors.items %}
  12. {{ error }}
  13. {% endfor %}
  14. {{ msg }}
  15. </div>
  16. <input type="hidden" name="sms_type" value="1">
  17. <input class="btn btn-green" id="jsFindPwdBtn" type="submit" value="提交" />
  18. <p class="form-p" style="bottom:40px;">您还可以<a href="/login/"> [直接登录]</a></p>
  19. {% csrf_token %}
  20. </form>

密码重置

配置路由

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

逻辑代码

  1. # 重置密码的view
  2. class ResetView(View):
  3. def get(self, request, active_code):
  4. # 查询邮箱验证记录是否存在
  5. all_record = EmailVerifyRecord.objects.filter(code=active_code)
  6. # 如果不为空也就是有用户
  7. if all_record:
  8. for record in all_record:
  9. # 获取到对应的邮箱
  10. email = record.email
  11. # 将email传回来
  12. return render(request, "password_reset.html", {"email":email})
  13. # 自己瞎输的验证码
  14. else:
  15. return render(
  16. request, "forgetpwd.html", {
  17. "msg": "您的重置密码链接无效,请重新请求"})

创建修改密码的form表单

  1. # 重置密码form实现
  2. class ModifyPwdForm(forms.Form):
  3. # 密码不能小于5位
  4. password1 = forms.CharField(required=True, min_length=5)
  5. # 密码不能小于5位
  6. password2 = forms.CharField(required=True, min_length=5)

配置路由

  1. path('modify_pwd/', ModifyPwdView.as_view(), name='modify_pwd'),

逻辑代码

  1. # 修改密码
  2. class ModifyPwdView(View):
  3. def post(self, request):
  4. modiypwd_form = ModifyPwdForm(request.POST)
  5. if modiypwd_form.is_valid():
  6. pwd1 = request.POST.get("password1", "")
  7. pwd2 = request.POST.get("password2", "")
  8. email = request.POST.get("email", "")
  9. # 如果两次密码不相等,返回错误信息
  10. if pwd1 != pwd2:
  11. return render(request, "password_reset.html", {"email": email, "msg": "密码不一致"})
  12. # 如果密码一致
  13. user = UserProfile.objects.get(email=email)
  14. # 加密成密文
  15. user.password = make_password(pwd2)
  16. # save保存到数据库
  17. user.save()
  18. return render(request, "login.html", {"msg": "密码修改成功,请登录"})
  19. # 验证失败说明密码位数不够。
  20. else:
  21. email = request.POST.get("email", "")
  22. return render(request, "password_reset.html", {"email": email, "modiypwd_form":modiypwd_form})

需要两个类是因为get请求和post请求参数不同

html文件根据以前的方法进行配置即可

Django+Xadmin打造在线教育系统(三)的更多相关文章

  1. Django+Xadmin打造在线教育系统(四)

    完成授课机构的功能 模板继承 在templates目录下,新建base.html,剪切org-list.html内容到里面 编写org-list.html内容 继承base.html,将里面的面包屑和 ...

  2. Django+Xadmin打造在线教育系统(二)

    基于xadmin的后台管理 先使用pip进行安装xadmin及其依赖包 pip install django-adminx 安装完成后卸载xadmin,保留依赖包即可 pip uninstall dj ...

  3. Django+Xadmin打造在线教育系统(九)

    xadmin的进阶开发 因版本问题.有些配置可能无效 自定义icon xadmin的图标采用的是第三方css样式font awesome,我们可以进官网下载最新的样式替代原本的,下载地址:http:/ ...

  4. Django+Xadmin打造在线教育系统(八)

    首页和全局404,500配置 轮播图 公开课 授课机构 新建view ## 首页view class IndexView(View): def get(self,request): # 取出轮播图 a ...

  5. Django+Xadmin打造在线教育系统(七)

    全局导航&个人中心&全局搜索 配置全局导航 让index页面也继承base页面,注意首页有个单独的__index.js__ base页面的导航栏也进行配置 <nav> &l ...

  6. Django+Xadmin打造在线教育系统(一)

    系统概括: 系统具有完整的用户登录注册以及找回密码功能,拥有完整个人中心. 个人中心: 修改头像,修改密码,修改邮箱,可以看到我的课程以及我的收藏.可以删除收藏,我的消息. 导航栏: 公开课,授课讲师 ...

  7. Django+Xadmin打造在线教育系统(五)

    课程相关功能实现 课程列表 创建课程相关的urls.py path("course/", include('course.urls', namespace="course ...

  8. Django+Xadmin打造在线教育系统(六)

    讲师相关功能实现 拷贝并修改teacher-list.html和teacher-detail.html, 继承base模板 # 讲师列表 path('teacher_list/', TeacherLi ...

  9. Django+xadmin打造在线教育平台(三)

    五.完成注册.找回密码和激活验证码功能 5.1.用户注册 register.html拷贝到templates目录 (1)users/views.py class RegisterView(View): ...

随机推荐

  1. Dockerfile centos7_tomcat7.0.64_jdk7u80

    FROM centos:7 MAINTAINER jiangzhehao WORKDIR /tmp RUN yum -y install net-tools ADD jdk-7u80-linux-x6 ...

  2. i++ 相比 ++i 哪个更高效?为什么?

    ++i的效率高些,++i在运算过程中不产生临时对象,返回的就是i,是个左值,类似++i=1这样的表达式是合法的,而i++在运算的过程中会产生临时对象,返回的是零时对象的值,是个右值,像i++=1这样的 ...

  3. rabbitmq集群运维一点总结

    说明:以下操作都以三节点集群为例,机器名标记为机器A.机器B.机器C,如果为双节点忽略机器C,如果为各多节点则与机器C操作相同 一.rabbitmq集群必要条件 1.1.绑定实体ip,即ip a所能查 ...

  4. socket流程

  5. asp.net mvc或者其他程序无法打开excel——解决方案,C#处理Excel文件

    问题描述:今天处理Excel时遇到一个问题,本地使用Microsoft.Jet.OLEDB.4.0处理,正常完成了需求, 上传到服务器后发生了异常,通过排查发现问题出现在对Excel文件的读取上,然后 ...

  6. c++ 单引号"字符串" 用法

    __int64 flag; //赋值超过4字节,编译错误 //flag = 'ABCDE'; //低于4字节,高位补 0 //flag = 'BCDE'; flag = 'A' << 24 ...

  7. Java Serializable的使用和transient关键字使用小记(转载)

    一:Serializable 1.持久化的简单介绍: “持久化”意味着对象的“生存时间”并不取决于程序是否正在执行——它存在或“生存”于程序的每一次调用之间.通过序列化一个对象,将其写入磁盘,以后在程 ...

  8. day 7-17 多表查询

    一. 准备表 #部门表 create table dep( id int, name varchar(20) ); #员工表 create table emp( id int primary key ...

  9. org.elasticsearch.client.transport.NoNodeAvailableException

    SpringBoot连接elasticsearch异常 2018-09-11 16:03:43.692 ERROR 8684 --- [ main] o.s.boot.SpringApplicatio ...

  10. from组件补充

    一.定义的规则 class TeacherForm(Form): #必须继承Form # 创建字段,本质上是正则表达式 username = fields.CharField( required=Tr ...