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