Django+xadmin 打造线上教育平台(二)
一、首页
1)views.py/index函数:
def index(request): """首页""" return render(request,"index.html")
2)html页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" >
<title>课程机构列表 - 慕学在线网</title>
<link rel="stylesheet" type="text/css" href="/static/css/reset.css">
<link rel="stylesheet" type="text/css" href="/static/css/animate.css">
<link rel="stylesheet" type="text/css" href="/static/css/style.css">
<script src="/static/js/jquery.min.js" type="text/javascript"></script>
<script src="/static/js/jquery-migrate-1.2.1.min.js" type="text/javascript"></script>
</head>
<body>
<section class="headerwrap ">
<header>
<div class=" header">
<div class="top">
<div class="wp">
<div class="fl"><p>服务电话:<b>33333333</b></p></div>
<!--登录后跳转-->
<!-- <a style="color:white" class="fr registerbtn" href="register.html">注册</a> -->
<!-- <a style="color:white" class="fr loginbtn" href="login.html">登录</a> -->
{% if request.user.is_authenticated%}
<div class="personal">
<dl class="user fr">
<dd>{{ request.user }}<img class="down fr" src="/static/images/top_down.png"/></dd>
<dt><img width="20" height="20" src="/static/media/image/2016/12/default_big_14.png"/></dt>
</dl>
<div class="userdetail">
<dl>
<dt><img width="80" height="80" src="/static/media/image/2016/12/default_big_14.png"/></dt>
<dd>
<h2>django</h2>
<p>{{ request.user }}</p>
</dd>
</dl>
<div class="btn">
<a class="personcenter fl" href="#">进入个人中心</a>
<a class="fr" href="/logout/">退出</a>
</div>
</div>
</div>
{% else %}
<a style="color:white" class="fr registerbtn" href="/register/">注册</a>
<a style="color:white" class="fr loginbtn" href="/login/">登录</a>
{% endif %}
</div>
</div>
{# header部分#}
<div class="middle">
<div class="wp">
<a href="/index/"><img class="fl" src="/static/images/logo.jpg"/></a>
<div class="searchbox fr">
<div class="selectContainer fl">
<span class="selectOption" id="jsSelectOption" data-value="course">
公开课
</span>
<ul class="selectMenu" id="jsSelectMenu">
<li data-value="course">公开课</li>
<li data-value="org">课程机构</li>
<li data-value="teacher">授课老师</li>
</ul>
</div>
<input id="search_keywords" class="fl" type="text" value="" placeholder="请输入搜索内容"/>
<img class="search_btn fr" id="jsSearchBtn" src="/static/images/search_btn.png"/>
</div>
</div>
</div>
<nav>
<div class="nav">
<div class="wp">
<ul>
<li class="active" ><a href="index.html">首页</a></li>
<li >
<a href="course-list.html">
公开课<img class="hot" src="/static/images/nav_hot.png">
</a>
</li>
<li >
<a href="teachers-list.html">授课教师</a>
</li>
<li ><a href="org-list.html">授课机构</a></li>
</ul>
</div>
</div>
</nav>
</div>
</header>
</section>
<!--crumbs start-->
{# 轮播图#}
<div class="banner">
<div class="wp">
<div class="fl">
<div class="imgslide">
<ul class="imgs">
<li>
<a href="http://www.imooc.com">
<img width="1200" height="478" src="/static/media/banner/2016/11/57a801860001c34b12000460.jpg" />
</a>
</li>
<li>
<a href="http://www.projectsedu.com">
<img width="1200" height="478" src="/static/media/banner/2016/11/57aa86a0000145c512000460.jpg" />
</a>
</li>
<li>
<a href="http://www.projectsedu.com">
<img width="1200" height="478" src="/static/media/banner/2016/11/57a801860001c34b12000460_z4Vb8zl.jpg" />
</a>
</li>
<li>
<a href="http://www.projectsedu.com">
<img width="1200" height="478" src="/static/media/banner/2016/11/57aa86a0000145c512000460_nMwvoQD.jpg" />
</a>
</li>
<li>
<a href="http://www.projectsedu.com">
<img width="1200" height="478" src="/static/media/banner/2016/11/57aa86a0000145c512000460_GXIBATC.jpg" />
</a>
</li>
</ul>
</div>
<div class="unslider-arrow prev"></div>
<div class="unslider-arrow next"></div>
</div>
</div>
</div>
<!--banner end-->
<!--feature start-->
<section>
<div class="wp">
<ul class="feature">
<li class="feature1">
<img class="pic" src="/static/images/feature1.png"/>
<p class="center">专业权威</p>
</li>
<li class="feature2">
<img class="pic" src="/static/images/feature2.png"/>
<p class="center">课程最新</p>
</li>
<li class="feature3">
<img class="pic" src="/static/images/feature3.png"/>
<p class="center">名师授课</p>
</li>
<li class="feature4">
<img class="pic" src="/static/images/feature4.png"/>
<p class="center">数据真实</p>
</li>
</ul>
</div>
</section>
<!--feature end-->
<!--module1 start-->
<section>
<div class="module">
<div class="wp">
<h1>公开课程</h1>
<div class="module1 eachmod">
<div class="module1_1 left">
<img width="228" height="614" src="/static/images/module1_1.jpg"/>
<p class="fisrt_word">名师授课<br/>专业权威</p>
<a class="more" href="course-list.html">查看更多课程 ></a>
</div>
<div class="right group_list">
<div class="module1_2 box">
<div class="imgslide2">
<ul class="imgs">
<li>
<a href="course-detail.html">
<img width="470" height="300" src="/static/media/courses/2016/12/python文件处理.jpg" />
</a>
</li>
<li>
<a href="course-detail.html">
<img width="470" height="300" src="/static/media/courses/2016/12/python面向对象.jpg" />
</a>
</li>
</ul>
</div>
<div class="unslider-arrow2 prev"></div>
<div class="unslider-arrow2 next"></div>
</div>
<div class="module1_3 box">
<a href="course-detail.html">
<img width="233" height="190" src="/static/media/courses/2016/11/mysql.jpg"/>
</a>
<div class="des">
<a href="course-detail.html">
<h2 title="django入门">django入门</h2>
</a>
<span class="fl">难度:<i class="key">初级</i></span>
<span class="fr">学习人数:3</span>
</div>
<div class="bottom">
<span class="fl" title="慕课网">慕课网</span>
<span class="star fr">0</span>
</div>
</div>
<div class="module1_4 box">
<a href="course-detail.html">
<img width="233" height="190" src="/static/media/courses/2016/11/57035ff200014b8a06000338-240-135.jpg"/>
</a>
<div class="des">
<a href="course-detail.html">
<h2 title="java入门">java入门</h2>
</a>
<span class="fl">难度:<i class="key">中级</i></span>
<span class="fr">学习人数:0</span>
</div>
<div class="bottom">
<span class="fl" title="北京大学">北京大学</span>
<span class="star fr">0</span>
</div>
</div>
<div class="module1_5 box">
<a href="course-detail.html">
<img width="233" height="190" src="/static/media/courses/2016/11/540e57300001d6d906000338-240-135.jpg"/>
</a>
<div class="des">
<a href="course-detail.html">
<h2 title="python入门">python入门</h2>
</a>
<span class="fl">难度:<i class="key">中级</i></span>
<span class="fr">学习人数:0</span>
</div>
<div class="bottom">
<span class="fl" title="南京大学">南京大学</span>
<span class="star fr">0</span>
</div>
</div>
<div class="module1_6 box">
<a href="course-detail.html">
<img width="233" height="190" src="/static/media/courses/2016/11/57035ff200014b8a06000338-240-135_dHfj8Nq.jpg"/>
</a>
<div class="des">
<a href="course-detail.html">
<h2 title="java入门2">java入门2</h2>
</a>
<span class="fl">难度:<i class="key">高级</i></span>
<span class="fr">学习人数:0</span>
</div>
<div class="bottom">
<span class="fl" title="慕课网2">慕课网2</span>
<span class="star fr">0</span>
</div>
</div>
<div class="module1_7 box">
<a href="course-detail.html">
<img width="233" height="190" src="/static/media/courses/2016/11/57035ff200014b8a06000338-240-135_0nFiBSI.jpg"/>
</a>
<div class="des">
<a href="course-detail.html">
<h2 title="java入门3">java入门3</h2>
</a>
<span class="fl">难度:<i class="key">初级</i></span>
<span class="fr">学习人数:1</span>
</div>
<div class="bottom">
<span class="fl" title="慕课网3">慕课网3</span>
<span class="star fr">0</span>
</div>
</div>
<div class="module1_8 box">
<a href="course-detail.html">
<img width="233" height="190" src="/static/media/courses/2016/11/540e57300001d6d906000338-240-135_MSIqfvw.jpg"/>
</a>
<div class="des">
<a href="course-detail.html">
<h2 title="python入门2">python入门2</h2>
</a>
<span class="fl">难度:<i class="key">中级</i></span>
<span class="fr">学习人数:0</span>
</div>
<div class="bottom">
<span class="fl" title="慕课网666">慕课网666</span>
<span class="star fr">0</span>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section>
<div class="module greybg">
<div class="wp">
<h1>课程机构</h1>
<div class="module3 eachmod">
<div class="module3_1 left">
<img width="228" height="463" src="/static/images/module3_1.jpg"/>
<p class="fisrt_word">名校来袭<br/>权威认证</p>
<a class="more" href="org-list.html">查看更多机构 ></a>
</div>
<div class="right">
<ul>
<li class="">
<a href="org-detail-homepage.html">
<div class="company">
<img width="184" height="100" src="/static/media/org/2016/11/imooc.png"/>
<div class="score">
<div class="circle">
<h2>全国知名</h2>
</div>
</div>
</div>
<p><span class="key" title="慕课网">慕课网</span></p>
</a>
</li>
<li class="">
<a href="org-detail-homepage.html">
<div class="company">
<img width="184" height="100" src="/static/media/org/2016/11/bjdx.jpg"/>
<div class="score">
<div class="circle">
<h2>全国知名</h2>
</div>
</div>
</div>
<p><span class="key" title="北京大学">北京大学</span></p>
</a>
</li>
<li class="">
<a href="org-detail-homepage.html">
<div class="company">
<img width="184" height="100" src="/static/media/org/2016/11/qhdx-logo.png"/>
<div class="score">
<div class="circle">
<h2>全国知名</h2>
</div>
</div>
</div>
<p><span class="key" title="清华大学">清华大学</span></p>
</a>
</li>
<li class="">
<a href="org-detail-homepage.html">
<div class="company">
<img width="184" height="100" src="/static/media/org/2016/11/njdx.jpg"/>
<div class="score">
<div class="circle">
<h2>全国知名</h2>
</div>
</div>
</div>
<p><span class="key" title="南京大学">南京大学</span></p>
</a>
</li>
<li class="five">
<a href="org-detail-homepage.html">
<div class="company">
<img width="184" height="100" src="/static/media/org/2016/11/imooc_klgAUn5.png"/>
<div class="score">
<div class="circle">
<h2>全国知名</h2>
</div>
</div>
</div>
<p><span class="key" title="慕课网2">慕课网2</span></p>
</a>
</li>
<li class="">
<a href="org-detail-homepage.html">
<div class="company">
<img width="184" height="100" src="/static/media/org/2016/11/imooc_Gn1sRjp.png"/>
<div class="score">
<div class="circle">
<h2>全国知名</h2>
</div>
</div>
</div>
<p><span class="key" title="慕课网3">慕课网3</span></p>
</a>
</li>
<li class="">
<a href="org-detail-homepage.html">
<div class="company">
<img width="184" height="100" src="/static/media/org/2016/11/imooc_Y2Tonsq.png"/>
<div class="score">
<div class="circle">
<h2>全国知名</h2>
</div>
</div>
</div>
<p><span class="key" title="慕课网3">慕课网3</span></p>
</a>
</li>
<li class="">
<a href="org-detail-homepage.html">
<div class="company">
<img width="184" height="100" src="/static/media/org/2016/11/imooc_OO2ykYP.png"/>
<div class="score">
<div class="circle">
<h2>全国知名</h2>
</div>
</div>
</div>
<p><span class="key" title="慕课网4">慕课网4</span></p>
</a>
</li>
<li class="">
<a href="org-detail-homepage.html">
<div class="company">
<img width="184" height="100" src="/static/media/org/2016/11/imooc_V0TJOyb.png"/>
<div class="score">
<div class="circle">
<h2>全国知名</h2>
</div>
</div>
</div>
<p><span class="key" title="慕课网5">慕课网5</span></p>
</a>
</li>
<li class="five">
<a href="org-detail-homepage.html">
<div class="company">
<img width="184" height="100" src="/static/media/org/2016/11/imooc_qEaMov1.png"/>
<div class="score">
<div class="circle">
<h2>全国知名</h2>
</div>
</div>
</div>
<p><span class="key" title="慕课网666">慕课网666</span></p>
</a>
</li>
<li class="">
<a href="org-detail-homepage.html">
<div class="company">
<img width="184" height="100" src="/static/media/org/2016/12/bjdx.jpg"/>
<div class="score">
<div class="circle">
<h2>全国知名</h2>
</div>
</div>
</div>
<p><span class="key" title="慕学网">慕学网</span></p>
</a>
</li>
<li class="">
<a href="org-detail-homepage.html">
<div class="company">
<img width="184" height="100" src="/static/media/org/2016/12/imooc_Gn1sRjp.png"/>
<div class="score">
<div class="circle">
<h2>全国知名</h2>
</div>
</div>
</div>
<p><span class="key" title="python培训机构">python培训机构</span></p>
</a>
</li>
<li class="">
<a href="org-detail-homepage.html">
<div class="company">
<img width="184" height="100" src="/static/media/org/2016/12/bjdx_cCpdUw8.jpg"/>
<div class="score">
<div class="circle">
<h2>全国知名</h2>
</div>
</div>
</div>
<p><span class="key" title="vuejs培训">vuejs培训</span></p>
</a>
</li>
<li class="">
<a href="org-detail-homepage.html">
<div class="company">
<img width="184" height="100" src="/static/media/org/2016/12/imooc_klgAUn5.png"/>
<div class="score">
<div class="circle">
<h2>全国知名</h2>
</div>
</div>
</div>
<p><span class="key" title="nodejs培训">nodejs培训</span></p>
</a>
</li>
<li class="five">
<a href="org-detail-homepage.html">
<div class="company">
<img width="184" height="100" src="/static/media/org/2016/12/bjdx_bcd0m07.jpg"/>
<div class="score">
<div class="circle">
<h2>全国知名</h2>
</div>
</div>
</div>
<p><span class="key" title="慕学在线">慕学在线</span></p>
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
</section>
<footer>
<div class="footer">
<div class="wp">
<ul class="cont">
<li class="logo"><a href=""><img src="/static/images/footlogo.png"/></a></li>
<li class="code"><img src="/static/images/code.jpg"/><p class="center">扫描关注微信</p></li>
<li class="third"><img class="fl" src="/static/images/tell.png"/><p class="tell">33333333</p><p class="time">周一至周日 9:00-18:00</p></li>
</ul>
</div>
<p class="line"></p>
<div class="wp clear">
<span class="fl">? 2016 www.projectsedu.com 慕学在线-在线学习交流平台 保留所有权利</span>
<span class="fr">copyright ? 2016 ICP备案证书号:蜀ICP备xxxxx号-1</span>
</div>
</div>
</footer>
<section>
<ul class="sidebar">
<li class="qq">
<a target="_blank" href="http://wpa.qq.com/msgrd?v=3&uin=2023525077&site=qq&menu=yes"></a>
</li>
<li class="totop"></li>
</ul>
</section>
<script src="/static/js/selectUi.js" type='text/javascript'></script>
<script src="/static/js/deco-common.js" type='text/javascript'></script>
<script type="text/javascript" src="/static/js/plugins/laydate/laydate.js"></script>
<script src="/static/js/plugins/layer/layer.js"></script>
<script src="/static/js/plugins/queryCity/js/public.js" type="text/javascript"></script>
<script src="/static/js/unslider.js" type="text/javascript"></script>
<script src="/static/js/plugins/jquery.scrollLoading.js" type="text/javascript"></script>
<script src="/static/js/deco-common.js" type="text/javascript"></script>
<script type="text/javascript" src="/static/js/index.js"></script>
</body>
</html>
3)Mxonline/url.py配置:
from django.urls import path,include,re_path from MxOnline import views urlpatterns = [ path('index/', views.index, name = 'index'), ]
二、登录
涉及:
- django自带form表单验证
- django自带authenticate验证方法
当用户登录进行authenticate时,会转到我们重新的CustomBackend类进行authenticate验证 ,前提需要将authenticate认证相关配置配置到setting中
1、django自带form表单验证:
LoginForm:
class LoginForm(forms.Form): '''登录验证表单''' username = forms.CharField(required=True) password = forms.CharField(required=True,min_length=5)
2、重写django自带authenticate验证:
1)在setting.py中配置:
AUTHENTICATION_BACKENDS = ( # 登录认证设置 'MxOnline.views.CustomBackend', #CustomBackend所在路径 )
2)在MxOnline/views中创建CustomBackend类:
from django.contrib.auth.backends import ModelBackend from users.models import UserProfile class CustomBackend(ModelBackend): """ 用于mx_login下的authenticate, setting中需配置全局路径AUTHENTICATION_BACKENDS,当用户登录验证时,用到mx_login下的authenticate进行验证,会 跳到此处进行验证 """ def authenticate(self, request, username=None, password=None, **kwargs):# 重写authenticate方法 try: # 不希望用户存在两个,get的结果只能有一个,否则报错 user = UserProfile.objects.get(Q(username=username)|Q(email=username)) print(user) # django的后台中密码是加密处理的,拿到客户登录的密码需要加密后才能对比判断,所以不能直接password==password # UserProfile继承的AbstractUser中有check_password()方法,会直接将传入的密码加密后于后台的作比较: print(user.check_password(password)) if user.check_password(password):# 如果为False,则密码不一致,否则密码正确 return user except Exception as e: return None
3)views.py/login:
from django.shortcuts import render,redirect,HttpResponse from django.contrib.auth import authenticate ,login ,logout def mx_login(request): """登录""" login_form = forms.LoginForm() if request.method == "POST": login_form = forms.LoginForm(request.POST) if login_form.is_valid():# form验证通过 # 获取用户提交的用户名和密码 user_name = request.POST.get('username', None) pass_word = request.POST.get('password', None) # 成功返回user对象,失败None user = authenticate(username=user_name, password=pass_word) # 如果不是null说明验证成功 if user: if user.is_active: # 只有注册激活才能登录 login(request, user) # request.session["is_login"] = True # request.session["username"] = user_name # request.session.set_expiry(5) return redirect("/index/") else: return render(request, 'login.html', {'msg': '用户未激活', 'login_form': login_form}) # 账号或密码错误 else: return render(request, 'login.html', {'msg': '用户名或密码错误','login_form': login_form}) else: return render(request, 'login.html', {'msg': '请正确输入用户名及密码','login_form': login_form}) # return render(request,'login.html',{'login_form': login_form}) return render(request,'login.html')
4)url.py配置:
path('login/', views.mx_login, name = 'login'),
5)html页面:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" >
<title>慕学在线网登录</title>
<link rel="stylesheet" type="text/css" href="/static/css/reset.css">
<link rel="stylesheet" type="text/css" href="/static/css/login.css">
</head>
<body>
<div class="dialog" id="jsDialog">
<!--提示弹出框-->
<div class="successbox dialogbox" id="jsSuccessTips">
<h1>成功提交</h1>
<div class="close jsCloseDialog"><img src="/static/images/dig_close.png"/></div>
<div class="cont">
<h2>您的需求提交成功!</h2>
<p></p>
</div>
</div>
<div class="noactivebox dialogbox" id="jsUnactiveForm" >
<h1>邮件验证提示</h1>
<div class="close jsCloseDialog"><img src="/static/images/dig_close.png"/></div>
<div class="center">
<img src="/static/images/send.png"/>
<p>我们已经向您的邮箱<span class="green" id="jsEmailToActive">12@13.com</span>发送了邮件,<br/>为保证您的账号安全,请及时验证邮箱</p>
<p class="a"><a class="btn" id="jsGoToEmail" target="_blank" href="http://mail.qq.com">去邮箱验证</a></p>
<p class="zy_success upmove"></p>
<p style="display: none;" class="sendE2">没收到,您可以查看您的垃圾邮件和被过滤邮件,也可以再次发送验证邮件(<span class="c5c">60s</span>)</p>
<p class="sendE">没收到,您可以查看您的垃圾邮件和被过滤邮件,<br/>也可以<span class="c5c green" id="jsSenEmailAgin" style="cursor: pointer;">再次发送验证邮件</span></p>
</div>
</div>
</div>
<div class="bg" id="dialogBg"></div>
<header>
<div class="c-box fff-box">
<div class="wp header-box">
<p class="fl hd-tips">慕学在线网,在线学习平台!</p>
<ul class="fr hd-bar">
<li>服务电话:<span>33333333</span></li>
<li class="active"><a href="{% url 'login' %}">[登录]</a></li>
<li><a href="{% url 'register' %}">[注册]</a></li>
</ul>
</div>
</div>
</header>
<section>
<div class="c-box bg-box">
<div class="login-box clearfix">
<div class="hd-login clearfix">
<a class="index-logo" href="/index/"></a>
<h1>用户登录</h1>
<a class="index-font" href="/index/">回到首页</a>
</div>
<div class="fl slide">
<div class="imgslide">
<ul class="imgs">
<li><a href=""><img width="483" height="472" src="/static/images/mysql.jpg"/></a></li>
<li><a href=""><img width="483" height="472" src="/static/images/mysql.jpg"/></a></li>
<li><a href=""><img width="483" height="472" src="/static/images/mysql.jpg"/></a></li>
</ul>
</div>
<div class="unslider-arrow prev"></div>
<div class="unslider-arrow next"></div>
</div>
<div class="fl form-box">
<h2>帐号登录</h2>
<form action="/login/" method="post" autocomplete="off">
{% csrf_token %}
<div class="form-group marb20 {% if login_form.errors.username.0 %} errorput {% endif %}">
<label>用 户 名</label>
<input name="username" id="account_l" type="text" placeholder="手机号/邮箱" value="{{ login_form.username.value }}"/>
</div>
<div class="error btns login-form-tips" id="jsLoginTips">{{ login_form.errors.username.0 }}</div>
<div class="form-group marb8 {% if login_form.errors.password.0 %} errorput {% endif %}">
<label>密 码</label>
<input name="password" id="password_l" type="password" value="{{ login_form.password.value }}" placeholder="请输入您的密码"/>
</div>
<div class="error btns login-form-tips" id="jsLoginTips">{{ login_form.errors.password.0 }}</div>
<div class="error btns login-form-tips" id="jsLoginTips">{{ msg }}</div>
<div class="auto-box marb38">
<a class="fr" href="{% url 'forgetpwd' %}">忘记密码?</a>
</div>
<input class="btn btn-green" id="jsLoginBtn" type="submit" value="立即登录 > "/>
<input type='hidden' name='csrfmiddlewaretoken' value='5I2SlleZJOMUX9QbwYLUIAOshdrdpRcy'/>
{% csrf_token %}
</form>
<p class="form-p">没有慕学在线网帐号?<a href="{% url 'register' %}">[立即注册]</a></p>
</div>
</div>
</div>
</section>
<script src="/static/js/jquery.min.js" type="text/javascript"></script>
<script src="/static/js/unslider.js" type="text/javascript"></script>
<script src="/static/js/login.js" type="text/javascript"></script>
</body>
</html>
三、退出登录
1、views.py/logout:
def mx_logout(request): """退出登录""" logout(request) return render(request,'index.html')
2、url.py:
path('logout/', views.mx_logout, name = 'logout'),
无HTML页面:
四、注册
客户注册,涉及验证码方面,需要安装captcha相关
步骤:
- 客户注册账号,验证账号、密码、验证码
- 客户提交注册信息,系统自动给客户回复一封邮件,用于激活账号
- 客户收到邮件并打开激活,激活成功可正常登录
1、views.py/register:
from django.shortcuts import render,redirect,HttpResponse from MxOnline import forms from users.models import UserProfile from django.contrib.auth.hashers import make_password from utils import email_send def register(request): """用户注册""" if request.method == "POST": register_form = forms.RegisterForm(request.POST) if register_form.is_valid(): user_name = request.POST.get('email',None) if UserProfile.objects.filter(email=user_name): # 用户已经存在,不用再注册 return render(request,'register.html',{'msg':'用户已经存在','register_form':register_form}) pass_word = request.POST.get('password',None) pass_word = make_password(pass_word) # 密码加密后再保存 UserProfile.objects.create( username=user_name, email=user_name, is_active=False, password=pass_word ) email_send.send_register_email(user_name,'register') # 发送邮件,用户激活账号 return redirect('/login/') else: status_form = True #用于前端注册时判断是否填充客户输入原数据 return render(request,'register.html',locals()) else: register_form = forms.RegisterForm() return render(request,'register.html',{'register_form':register_form})
涉及到django自带的邮件功能:
1)setting.py中配置email相关:
# 邮箱配置 EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = "smtp.163.com" #以163邮箱为例,SMTP服务器(邮箱需要开通SMTP服务) EMAIL_HOST_PASSWORD = '******' #SMTP服务授权码 DEFAULT_FROM_EMAIL = EMAIL_HOST_USER = "name@163.com" #我的163邮箱帐号 EMAIL_PORT = 25 #163邮箱SMTP服务端口 EMAIL_USE_TLS = True # 163、qq邮箱此值为True,aliyun此值为False,163可以忽略此值 EMAIL_SUBJECT_PREFIX = '[yshblog.com]' #邮件标题前缀,默认是'[django]'
2)新建email_send.py:
- 生成随机验证码
- 发送邮件相关
import random from users.models import EmailVerifyRecord from django.core.mail import send_mail from MxOnline import settings # 验证码生成 def random_str(random_length=16): """默认生成16位随机字符串""" str = '' # 生成字符串的可选字符串 chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789' length = len(chars) - 1 ran_dom = random.Random() for i in range(random_length): str += chars[random.randint(0, length)] return str # 发送邮件 def send_register_email(email, send_type="register"): """ 发送邮件 发送前需要先保存到数据库,到时候查询链接是否存在 """ if send_type == 'update_email': # 修改密码操作 code = random_str(4) else: code = random_str(16) # 保存到数据库 EmailVerifyRecord.objects.create( code=code, email=email, send_type=send_type ) # 定义邮箱内容: if send_type == "register": subject = "Mx在线教育注册激活链接" # 标题 email_body = "请复制打开下面的链接激活你的账号:http://127.0.0.1:8000/active/{0}".format(code) # 文本邮件体 sender = settings.DEFAULT_FROM_EMAIL # 发件人 receiver = [email] # 接收人 email_send_status = send_mail(subject, email_body, sender, receiver) return email_send_status # if email_send_status: # pass elif send_type == 'forget': subject = "Mx在线教育重置密码链接" # 标题 email_body = "请复制打开下面的链接重置密码:http://127.0.0.1:8000/reset/{0}".format(code) # 文本邮件体 sender = settings.DEFAULT_FROM_EMAIL # 发件人 receiver = [email] # 接收人 email_send_status = send_mail(subject, email_body, sender, receiver) return email_send_status
3)url.py配置:
path('register/', views.register, name = 'register'), # 注册
3.1)发送邮件后客户打开邮件激活账号,需要再user_active(用户账号激活)函数:
def user_active(request,ac_code): """用户账号激活""" if request.method == "GET": ac_record = EmailVerifyRecord.objects.filter(code=ac_code,) if ac_record: ac_email = ac_record[0].email ac_user = UserProfile.objects.get(email=ac_email) ac_user.is_active = True ac_user.save() else: return render(request,'active_fail.html') email_count = ac_record[0].email # return render(request,'login.html',{'email_count':email_count}) return render(request,'active_success.html',{'email_count':email_count})
3.2)url.py配置:
re_path(r'^active/(\w+)/',views.user_active,name='user_active'),# 邮箱激活账号
4)HTML页面:
<!DOCTYPE html> {% load staticfiles %} <html> <head> <meta charset="UTF-8"> <meta name="renderer" content="webkit"> <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" > <title>慕学在线注册</title> <link rel="stylesheet" type="text/css" href="{% static 'css/reset.css' %}"> <link rel="stylesheet" type="text/css" href="{% static 'css/login.css' %}"> </head> <body> <div class="loginbox dialogbox"> <h1>账号登录</h1> <div class="close jsCloseDialog"><img src="{% static 'images/dig_close.png' %}"/></div> <div class="cont"> <form id="jsLoginForm" autocomplete="off"> <div class="box"> <span class="word3">用户名</span> <input type="text" name="account_l" id="account_l" placeholder="手机号/邮箱" /> </div> <div class="box"> <span class="word2">密 码</span> <input type="password" name="password_l" id="password_l" placeholder="请输入您的密码"/> </div> <div class="error btns login-form-tips" id="jsLoginTips"></div> <!--登录错误提示--> <div class="btns"> <span><input type="checkbox" id="jsAutoLogin" /> 自动登录</span> <span class="forget btn fr">忘记密码</span> </div> <div class="button"> <input type="button" value="登录" id="jsLoginBtn" /> </div> <div class="btns"> <span class="fr">没有账号?<span class="regist btn">立即注册</span></span> </div> </form> </div> </div> <div class="dialog" id="jsDialog"> <!--提示弹出框--> <div class="successbox dialogbox" id="jsSuccessTips"> <h1>成功提交</h1> <div class="close jsCloseDialog"><img src="{% static 'images/dig_close.png' %}"/></div> <div class="cont"> <h2>您的需求提交成功!</h2> <p></p> </div> </div> <div class="noactivebox dialogbox" id="jsUnactiveForm" > <h1>邮件验证提示</h1> <div class="close jsCloseDialog"><img src="{% static 'images/dig_close.png' %}"/></div> <div class="center"> <img src="{% static 'images/send.png' %}"/> <p>我们已经向您的邮箱<span class="green" id="jsEmailToActive">12@13.com</span>发送了邮件,<br/>为保证您的账号安全,请及时验证邮箱</p> <p class="a"><a class="btn" id="jsGoToEmail" target="_blank" href="http://mail.qq.com">去邮箱验证</a></p> <p class="zy_success upmove"></p> <p style="display: none;" class="sendE2">没收到,您可以查看您的垃圾邮件和被过滤邮件,也可以再次发送验证邮件(<span class="c5c">60s</span>)</p> <p class="sendE">没收到,您可以查看您的垃圾邮件和被过滤邮件,<br/>也可以<span class="c5c green" id="jsSenEmailAgin" style="cursor: pointer;">再次发送验证邮件</span></p> </div> </div> </div> <div class="bg" id="dialogBg"></div> <header> <div class="c-box fff-box"> <div class="wp header-box"> <p class="fl hd-tips">慕学在线,在线学习平台!</p> <ul class="fr hd-bar"> <li>服务电话:<span>4001008031</span></li> <li><a href="{% url 'login' %}">[登录]</a></li> <li class="active"><a href="{% url 'register' %}">[注册]</a></li> </ul> </div> </div> </header> <section> <div class="c-box bg-box"> <div class="login-box clearfix"> <div class="hd-login clearfix"> <a class="index-logo" href="/index/"></a> <h1>用户注册</h1> <a class="index-font" href="/index/">回到首页</a> </div> <div class="fl slide"> <div class="imgslide"> <ul class="imgs"> <li><a href=""><img width="483" height="472" src="{% static 'images/57a801860001c34b12000460.jpg' %}" /></a></li> <li><a href=""><img width="483" height="472" src="{% static 'images/57a801860001c34b12000460.jpg' %}" /></a></li> <li><a href=""><img width="483" height="472" src="{% static 'images/57a801860001c34b12000460.jpg' %}" /></a></li> </ul> </div> <div class="unslider-arrow prev"></div> <div class="unslider-arrow next"></div> </div> <div class="fl form-box"> <div class="tab"> <!--<h2 class="active">手机注册</h2>--> <h2>邮箱注册</h2> </div> <!--<div class="tab-form">--> <!--<form id="mobile_register_form" autocomplete="off">--> <!--<input type='hidden' name='csrfmiddlewaretoken' value='gTZljXgnpvxn0fKZ1XkWrM1PrCGSjiCZ' />--> <!--<div class="form-group marb20">--> <!--<label>手 机 号</label>--> <!--<input id="jsRegMobile" name="account" type="text" placeholder="请输入您的手机号码" />--> <!--</div>--> <!--<div class="form-group marb20" id="jsRefreshCode">--> <!--<label>验 证 码</label>--> <!--<input autocomplete="off" class="form-control-captcha mobile-register-captcha" id="mobile-register-captcha_1" name="captcha_m_1" placeholder="请输入验证码" type="text" /> <input class="form-control-captcha mobile-register-captcha" id="mobile-register-captcha_0" name="captcha_m_0" placeholder="请输入验证码" type="hidden" value="29953bacf7005e8469388b449d97d00d523c1706" /> <img src="/captcha/image/29953bacf7005e8469388b449d97d00d523c1706/" alt="captcha" class="captcha" />--> <!--</div>--> <!--<div class="clearfix">--> <!--<div class="form-group marb8 verify-code">--> <!--<label>短信验证码</label>--> <!--<input id="jsPhoneRegCaptcha" name="mobile_code" type="text" placeholder="输入手机验证码" />--> <!--</div>--> <!--<input class="verify-code-btn sendcode" id="jsSendCode" value="发送验证码">--> <!--</div>--> <!--<div class="form-group marb8">--> <!--<label>密 码</label>--> <!--<input id="jsPhoneRegPwd" name="password_m" type="password" placeholder="请输入6-20位非中文字符密码" />--> <!--</div>--> <!--<div class="error btns" id="jsMobileTips"></div>--> <!--<div class="auto-box marb8">--> <!--</div>--> <!--<input class="btn btn-green" id="jsMobileRegBtn" type="button" value="注册并登录" />--> <!--</form>--> <!--</div>--> <div class="tab-form"> <form id="email_register_form" method="post" action="{% url 'register' %}" autocomplete="off"> {% csrf_token %} <div class="form-group marb20 {% if register_form.errors.email.0 %} errorput {% endif %}"> <label>邮 箱</label> <input type="text" id="id_email" name="email" {% if status_form %} value="{{ register_form.email.value }}" {% endif %} placeholder="请输入您的邮箱地址" /> </div> <div class="error btns" id="jsEmailTips">{{ register_form.errors.email.0 }}</div> <div class="form-group marb8 {% if register_form.errors.password.0 %} errorput {% endif %}"> <label>密 码</label> <input type="password" id="id_password" name="password" {% if status_form %} value="{{ register_form.password.value }}" {% endif %} placeholder="请输入6-20位非中文字符密码" /> </div> <div class="error btns" id="jsEmailTips">{{ register_form.errors.password.0 }}</div> <div class="form-group marb8 captcha1 {% if register_form.errors.captchal.0 %} errorput {% endif %}"> <label>验 证 码</label> {{ register_form.captcha }} </div> <div class="error btns" id="jsEmailTips">{{ register_form.errors.captcha.0 }}</div> <div class="error btns" id="jsEmailTips"> {{ msg }} </div> <div class="auto-box marb8"> </div> <input class="btn btn-green" id="jsEmailRegBtn" type="submit" value="注册" /> </form> </div> <p class="form-p">已有账号?<a href="{% url 'login' %}">[立即登录]</a></p> </div> </div> </div> </section> <input id="isLogin" type="hidden" value="False"/> <script src="{% static 'js/jquery.min.js' %}" type="text/javascript"></script> <script src="{% static 'js/unslider.js' %}" type="text/javascript"></script> <script src="{% static 'js/validateDialog.js' %}" type="text/javascript"></script> <script src="{% static 'js/login.js' %}" type="text/javascript"></script> </body> </html>
至此,注册部分便完成了
五、忘记密码
步骤:
- 客户忘记密码,点击‘忘记密码’操作
- 根据客户提交用户信息,系统自动给用户发送邮件用于重置密码
- 客户打开邮件中提供的链接,进行密码重置
- 服务端更新该用户数据
1、忘记密码:

1.1)html页面代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="renderer" content="webkit">
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
<title>慕学网首页</title>
<link rel="stylesheet" type="text/css" href="/static/css/reset.css">
<link rel="stylesheet" type="text/css" href="/static/css/login.css">
</head>
<body>
<!--提示弹出框-->
<div class="successbox dialogbox" id="jsSuccessTips">
<h1>成功提交</h1>
<div class="close jsCloseDialog"><img src="/static/images/dig_close.png"/></div>
<div class="cont">
<h2>您的需求提交成功!</h2>
<p></p>
</div>
</div>
<div class="resetpassbox dialogbox" id="jsSetNewPwd">
<h1>重新设置密码</h1>
<div class="close jsCloseDialog"><img src="/static/images/dig_close.png"/></div>
<p class="green">请输入新密码</p>
<form id="jsSetNewPwdForm">
<div class="box">
<span class="word2">密 码</span>
<input type="password" name="password" id="jsResetPwd" placeholder="请输入新密码"/>
</div>
<div class="box">
<span class="word2">确 认 密 码</span>
<input type="password" name="password2" id="jsResetPwd2" placeholder="请再次输入新密码"/>
</div>
<div class="box">
<span class="word2">验 证 码</span>
<input type="text" name="code" id="jsResetCode" placeholder="请输入手机验证码"/>
</div>
<div class="error btns" id="jsSetNewPwdTips"></div>
<div class="button">
<input type="hidden" name="mobile" id="jsInpResetMobil"/>
<input id="jsSetNewPwdBtn" type="button" value="提交"/>
</div>
</form>
</div>
<div class="bg" id="dialogBg"></div>
<header>
<div class="c-box fff-box">
<div class="wp header-box">
<p class="fl hd-tips">慕学网,在线学习平台!</p>
<ul class="fr hd-bar">
<li>服务电话:<span>33333333</span></li>
<li><a href="{% url 'login' %}">[登录]</a></li>
<li class="active"><a href="/forgetpwd/">[忘记密码]</a></li>
</ul>
</div>
</div>
</header>
<section>
<div class="c-box bg-box">
<div class="login-box clearfix">
<div class="hd-login clearfix">
<a class="index-logo" href="{% url 'index' %}"></a>
<h1>忘记密码</h1>
<a class="index-font" href="{% url 'index' %}">回到首页</a>
</div>
<div class="fl slide">
<div class="imgslide">
<ul class="imgs">
<li><a href=""><img width="483" height="472" src="/static/images/57a801860001c34b12000460.jpg"/></a>
</li>
<li><a href=""><img width="483" height="472" src="/static/images/57a801860001c34b12000460.jpg"/></a>
</li>
<li><a href=""><img width="483" height="472" src="/static/images/57a801860001c34b12000460.jpg"/></a>
</li>
</ul>
</div>
<div class="unslider-arrow prev"></div>
<div class="unslider-arrow next"></div>
</div>
<div class="fl form-box">
<h2>忘记密码</h2>
<form id="jsFindPwdForm" method="post" autocomplete="off">
{% csrf_token %}
<div class="form-group marb20 {% if forgetpwd_form.errors.email.0 %} errorput {% endif %}">
<label>帐 号</label>
<input type="text" id="account" name="email" {% if message.status %} value="{{ forgetpwd_form.email.value }}" {% endif %} placeholder="请输入邮箱号"/>
</div>
<div class="form-group captcha1 marb38 {% if forgetpwd_form.errors.captchal.0 %} errorput {% endif %}">
<label>验 证 码</label>
{{ forgetpwd_form.captcha }}
</div>
<div class="error btns" id="jsForgetTips">{{ message.msg }}</div>
<input type="hidden" name="sms_type" value="1">
<input class="btn btn-green" id="jsFindPwdBtn" type="submit" value="提交"/>
<p class="form-p" style="bottom:40px;">您还可以<a href="{% url 'login' %}"> [直接登录]</a></p>
</form>
</div>
</div>
</div>
</section>
<input id="isLogin" type="hidden" value="False"/>
<script src="/static/js/jquery.min.js" type="text/javascript"></script>
<script src="/static/js/unslider.js" type="text/javascript"></script>
<script src="/static/js/validateDialog.js" type="text/javascript"></script>
<script src="/static/js/login.js" type="text/javascript"></script>
</body>
</html>
1.2)views.py/forget_pwd:
def forget_pwd(request): """忘记密码""" message ={} if request.method == "POST": forgetpwd_form = forms.ForgetPwdForm(request.POST) if forgetpwd_form.is_valid(): email = request.POST.get('email',None) user_count = UserProfile.objects.filter(email=email) if user_count:# 判断邮箱是否存在 send_status = email_send.send_register_email(email,'forget') # print("send:",send_status) if send_status: return render(request,'send_email_success.html') else: message['msg'] = '该邮箱不存在' message['status'] =True return render(request,'forgetpwd.html',{'message':message,'forgetpwd_form':forgetpwd_form}) else: # form表单验证不通过 message['msg'] = '邮箱或验证码错误' message['status'] = True return render(request,'forgetpwd.html',{'message':message,'forgetpwd_form':forgetpwd_form}) else: forgetpwd_form = forms.ForgetPwdForm() return render(request,'forgetpwd.html',{'forgetpwd_form':forgetpwd_form})
1.3)url.py配置:
path('forgetpwd/',views.forget_pwd,name='forgetpwd'), # 忘记密码
2、发送重置密码邮件后,客户点开邮件中提供的链接,需要再处理:
2.1)views.py/pwd_reset:
def pwd_reset(request,ac_code): """用户重置密码链接""" if request.method =="GET": records = EmailVerifyRecord.objects.filter(code=ac_code) if records: email = records[0].email return render(request, "password_reset.html", {"email": email}) else:# 链接不对 return render(request, "active_fail.html")
2,2)url.py配置:
re_path(r'^reset/(\w+)/',views.pwd_reset,name='reset'), # 邮箱重置密码链接
2.3)无HTML页面,打开重置密码的邮件后,访问邮件内提供的链接,可跳转到重置密码页面:

3、密码重置:
3.1)views.py/modify_pwd:
def modify_pwd(request): """重置密码""" if request.method == "POST": modify_form = forms.ModifyPwdForm(request.POST) if modify_form.is_valid(): pwd1 = request.POST.get("password1", None) pwd2 = request.POST.get("password2", None) email = request.POST.get("email", None) if pwd1 != pwd2: return render(request, "password_reset.html", {"email": email, "msg": "密码不一致!"}) user = UserProfile.objects.get(email=email) user.password = make_password(pwd2) user.save() return render(request, "login.html") else: email = request.POST.get("email", None) return render(request, "password_reset.html", {"email": email, "modify_form": modify_form})
3.2)url.py:
path('modify_pwd/',views.modify_pwd,name='modify_pwd'), # 重置密码 # 这是验证码的url配置 re_path(r'^captcha', include('captcha.urls')),
3.3)html页面:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="renderer" content="webkit"> <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1"> <title>密码修改</title> <link rel="stylesheet" type="text/css" href="/static/css/reset.css"> <link rel="stylesheet" type="text/css" href="/static/css/animate.css"> <link rel="stylesheet" type="text/css" href="/static/css/style.css"> <body> <div class="wp"> <div class="resetpassword" id="resetPwdForm"> <h1>修改密码</h1> <p>已经通过验证,请设置新密码</p> <form id="reset_password_form" action="{% url 'modify_pwd' %}" method="post"> {% csrf_token %} <ul> <li class="{% if modify_form.errors.password1.0 %} errorput {% endif %}"> <span class="">新 密 码 :</span> <input type="password" name="password1" id="pwd" placeholder="6-20位非中文字符"> <i></i> </li> <input type="hidden" name="email" value="{{ email }}"> <li class="{% if modify_form.errors.password2.0 %} errorput {% endif %}"> <span class="">确定密码:</span> <input type="password" name="password2" id="repwd" placeholder="6-20位非中文字符"> <i></i> </li> <div class="error btns" id="jsPasswdResetTips" style="color: red"> {% for key,error in modify_form.errors.items %}{{ key }}:{{ error }}{% endfor %}{{ msg }} </div> <li class="button"> <input type="submit" value="提交"> </li> </ul> </form> </div> <div class="resetpassword" id="reset_password_tips" style="display:none;"> <h1>修改密码成功,请重新登录</h1> <img class="fl" src="/static/images/check2.png"> <p class="successword">已经成功修改密码,请重新登录</p> </div> </div> </body> </html>
至此,用户登录-注册-重置密码方面便完成了
后端完整源码:
views:
from django.shortcuts import render,redirect,HttpResponse from django.contrib.auth import authenticate ,login ,logout from django.contrib.auth.backends import ModelBackend from MxOnline import forms from users.models import UserProfile,EmailVerifyRecord from django.db.models import Q from django.contrib.auth.hashers import make_password from utils import email_send # Create your views here. def index(request): """首页""" return render(request,"index.html") class CustomBackend(ModelBackend): """ 用于mx_login下的authenticate, setting中需配置全局路径AUTHENTICATION_BACKENDS,当用户登录验证时,用到mx_login下的authenticate进行验证,会 跳到此处进行验证 """ def authenticate(self, request, username=None, password=None, **kwargs):# 重写authenticate方法 try: # 不希望用户存在两个,get的结果只能有一个,否则报错 user = UserProfile.objects.get(Q(username=username)|Q(email=username)) print(user) # django的后台中密码是加密处理的,拿到客户登录的密码需要加密后才能对比判断,所以不能直接password==password # UserProfile继承的AbstractUser中有check_password()方法,会直接将传入的密码加密后于后台的作比较: print(user.check_password(password)) if user.check_password(password):# 如果为False,则密码不一致,否则密码正确 return user except Exception as e: return None def mx_login(request): """登录""" login_form = forms.LoginForm() if request.method == "POST": login_form = forms.LoginForm(request.POST) if login_form.is_valid():# form验证通过 # 获取用户提交的用户名和密码 user_name = request.POST.get('username', None) pass_word = request.POST.get('password', None) # 成功返回user对象,失败None user = authenticate(username=user_name, password=pass_word) # 如果不是null说明验证成功 if user: if user.is_active: # 只有注册激活才能登录 login(request, user) # request.session["is_login"] = True # request.session["username"] = user_name # request.session.set_expiry(5) return redirect("/index/") else: return render(request, 'login.html', {'msg': '用户未激活', 'login_form': login_form}) # 账号或密码错误 else: return render(request, 'login.html', {'msg': '用户名或密码错误','login_form': login_form}) else: return render(request, 'login.html', {'msg': '请正确输入用户名及密码','login_form': login_form}) # return render(request,'login.html',{'login_form': login_form}) return render(request,'login.html') def mx_logout(request): """退出登录""" logout(request) return render(request,'index.html') def register(request): """用户注册""" if request.method == "POST": register_form = forms.RegisterForm(request.POST) if register_form.is_valid(): user_name = request.POST.get('email',None) if UserProfile.objects.filter(email=user_name): # 用户已经存在,不用再注册 return render(request,'register.html',{'msg':'用户已经存在','register_form':register_form}) pass_word = request.POST.get('password',None) pass_word = make_password(pass_word) # 密码加密后再保存 UserProfile.objects.create( username=user_name, email=user_name, is_active=False, password=pass_word ) email_send.send_register_email(user_name,'register') # 发送邮件,用户激活账号 return redirect('/login/') else: status_form = True #用于前端注册时判断是否填充客户输入原数据 return render(request,'register.html',locals()) else: register_form = forms.RegisterForm() return render(request,'register.html',{'register_form':register_form}) def user_active(request,ac_code): """用户账号激活""" if request.method == "GET": ac_record = EmailVerifyRecord.objects.filter(code=ac_code,) if ac_record: ac_email = ac_record[0].email ac_user = UserProfile.objects.get(email=ac_email) ac_user.is_active = True ac_user.save() else: return render(request,'active_fail.html') email_count = ac_record[0].email # return render(request,'login.html',{'email_count':email_count}) return render(request,'active_success.html',{'email_count':email_count}) def forget_pwd(request): """忘记密码""" message ={} if request.method == "POST": forgetpwd_form = forms.ForgetPwdForm(request.POST) if forgetpwd_form.is_valid(): email = request.POST.get('email',None) user_count = UserProfile.objects.filter(email=email) if user_count:# 判断邮箱是否存在 send_status = email_send.send_register_email(email,'forget') # print("send:",send_status) if send_status: return render(request,'send_email_success.html') else: message['msg'] = '该邮箱不存在' message['status'] =True return render(request,'forgetpwd.html',{'message':message,'forgetpwd_form':forgetpwd_form}) else: # form表单验证不通过 message['msg'] = '邮箱或验证码错误' message['status'] = True return render(request,'forgetpwd.html',{'message':message,'forgetpwd_form':forgetpwd_form}) else: forgetpwd_form = forms.ForgetPwdForm() return render(request,'forgetpwd.html',{'forgetpwd_form':forgetpwd_form}) def pwd_reset(request,ac_code): """用户重置密码链接""" if request.method =="GET": records = EmailVerifyRecord.objects.filter(code=ac_code) if records: email = records[0].email return render(request, "password_reset.html", {"email": email}) else:# 链接不对 return render(request, "active_fail.html") # return render(request, "login.html") def modify_pwd(request): """重置密码""" if request.method == "POST": modify_form = forms.ModifyPwdForm(request.POST) if modify_form.is_valid(): pwd1 = request.POST.get("password1", None) pwd2 = request.POST.get("password2", None) email = request.POST.get("email", None) if pwd1 != pwd2: return render(request, "password_reset.html", {"email": email, "msg": "密码不一致!"}) user = UserProfile.objects.get(email=email) user.password = make_password(pwd2) user.save() return render(request, "login.html") else: email = request.POST.get("email", None) return render(request, "password_reset.html", {"email": email, "modify_form": modify_form})
url.py:
"""MxOnline URL Configuration The `urlpatterns` list routes URLs to views. For more information please see: https://docs.djangoproject.com/en/2.0/topics/http/urls/ Examples: Function views 1. Add an import: from my_app import views 2. Add a URL to urlpatterns: path('', views.home, name='home') Class-based views 1. Add an import: from other_app.views import Home 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ # from django.contrib import admin from django.urls import path,include,re_path import xadmin from MxOnline import views urlpatterns = [ path('xadmin/', xadmin.site.urls), path('index/', views.index, name = 'index'), path('login/', views.mx_login, name = 'login'), path('logout/', views.mx_logout, name = 'logout'), path('register/', views.register, name = 'register'), # re_path('active/(?P<active_code>.*)/',ActiveUserView.as_view(),name='user_active'), re_path(r'^active/(\w+)/',views.user_active,name='user_active'),# 邮箱激活账号 path('forgetpwd/',views.forget_pwd,name='forgetpwd'), # 忘记密码 re_path(r'^reset/(\w+)/',views.pwd_reset,name='reset'), # 邮箱重置密码链接 path('modify_pwd/',views.modify_pwd,name='modify_pwd'), # 重置密码 # 验证码 re_path(r'^captcha', include('captcha.urls')), ]
form.Form自定义表单:
from django import forms from captcha.fields import CaptchaField class LoginForm(forms.Form): '''登录验证表单''' username = forms.CharField(required=True) password = forms.CharField(required=True,min_length=5) class RegisterForm(forms.Form): '''注册验证表单''' email = forms.EmailField(required=True) password = forms.CharField(required=True,min_length=5) # 验证码 captcha = CaptchaField(error_messages={'invalid':'验证码错误'}) class ForgetPwdForm(forms.Form): '''忘记密码''' email = forms.EmailField(required=True) captcha = CaptchaField(error_messages={'invalid': '验证码错误'}) class ModifyPwdForm(forms.Form): '''重置密码''' password1 = forms.CharField(required=True, min_length=5) password2 = forms.CharField(required=True, min_length=5)
email_send.py:
import random from users.models import EmailVerifyRecord from django.core.mail import send_mail from MxOnline import settings def random_str(random_length=16): """默认生成16位随机字符串""" str = '' # 生成字符串的可选字符串 chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789' length = len(chars) - 1 ran_dom = random.Random() for i in range(random_length): str += chars[random.randint(0, length)] return str # 发送邮件 def send_register_email(email, send_type="register"): """ 发送邮件 发送前需要先保存到数据库,到时候查询链接是否存在 """ if send_type == 'update_email': # 修改密码操作 code = random_str(4) else: code = random_str(16) # 保存到数据库 EmailVerifyRecord.objects.create( code=code, email=email, send_type=send_type ) # 定义邮箱内容: if send_type == "register": subject = "Mx在线教育注册激活链接" # 标题 email_body = "请复制打开下面的链接激活你的账号:http://127.0.0.1:8000/active/{0}".format(code) # 文本邮件体 sender = settings.DEFAULT_FROM_EMAIL # 发件人 receiver = [email] # 接收人 email_send_status = send_mail(subject, email_body, sender, receiver) return email_send_status # if email_send_status: # pass elif send_type == 'forget': subject = "Mx在线教育重置密码链接" # 标题 email_body = "请复制打开下面的链接重置密码:http://127.0.0.1:8000/reset/{0}".format(code) # 文本邮件体 sender = settings.DEFAULT_FROM_EMAIL # 发件人 receiver = [email] # 接收人 email_send_status = send_mail(subject, email_body, sender, receiver) return email_send_status
浙公网安备 33010602011771号