Django+xadmin打造在线教育平台(八)
目录
代码
教程
学习自慕课网-使用python3.x与Django2.0.1开发的在线教育平台
十一、用户信息
11.1.个人信息展示
(1)新建‘usercenter-bae.html’当母板
{% load staticfiles %} <!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>{% block title %} 个人信息- 慕学在线网 {% endblock %}</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' %}"> <link rel="stylesheet" type="text/css" href="{% static 'js/plugins/queryCity/css/cityLayout.css' %}"> {% block custom_css %} {% endblock %} <link rel="stylesheet" type="text/css" href="{% static 'css/lq.datetimepick.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 headerwrap2"> <header> <div class="header2 header"> <div class="top"> <div class="wp"> <div class="fl"><p>服务电话:<b>33333333</b></p></div> <!--登录后跳转--> <div class="personal"> <dl class="user fr"> <dd>bobby<img class="down fr" src="{% static 'js/jquery-migrate-1.2.1.min.js' %}"/></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>bobby</p> </dd> </dl> <div class="btn"> <a class="personcenter fl" href="usercenter-info.html">进入个人中心</a> <a class="fr" href="/logout/">退出</a> </div> </div> </div> <a href="usercenter-message.html"> <div class="msg-num"><span id="MsgNum">0</span></div> </a> </div> </div> <div class="middle"> <div class="wp"> <a href="index.html"><img class="fl" src="{% static 'images/logo2.png' %}"/></a> <h1>我的慕学网</h1> </div> </div> </div> </header> </section> <!--crumbs start--> {% block custom_bread %} {% endblock %} <section> <div class="wp list personal_list"> <div class="left"> <ul> <li class="active2"><a href="usercenter-info.html">个人资料</a></li> <li ><a href="usercenter-mycourse.html">我的课程</a></li> <li ><a href="usercenter-fav-course.html">我的收藏</a></li> <li > <a href="usercenter-message.html" style="position: relative;"> 我的消息 </a> </li> </ul> </div> {% block custom_right_content %} {% endblock %} </div> </section> <script src="{% static 'js/selectUi.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/validateDialog.js' %}" type="text/javascript"></script> <script src="{% static 'js/deco-common.js' %}" type="text/javascript"></script> <script src="{% static 'js/plugins/jquery.upload.js' %}" type='text/javascript'></script> <script src="{% static 'js/validate.js' %}" type="text/javascript"></script> <script src="{% static 'js/deco-user.js' %}"></script> <script type="text/javascript"> $('.jsDeleteFav_course').on('click', function(){ var _this = $(this), favid = _this.attr('data-favid'); alert(favid) $.ajax({ cache: false, type: "POST", url: "/org/add_fav/", data: { fav_type: 1, fav_id: favid, csrfmiddlewaretoken: '799Y6iPeEDNSGvrTu3noBrO4MBLv6enY' }, async: true, success: function(data) { Dml.fun.winReload(); } }); }); $('.jsDeleteFav_teacher').on('click', function(){ var _this = $(this), favid = _this.attr('data-favid'); $.ajax({ cache: false, type: "POST", url: "/org/add_fav/", data: { fav_type: 3, fav_id: favid, csrfmiddlewaretoken: '799Y6iPeEDNSGvrTu3noBrO4MBLv6enY' }, async: true, success: function(data) { Dml.fun.winReload(); } }); }); $('.jsDeleteFav_org').on('click', function(){ var _this = $(this), favid = _this.attr('data-favid'); $.ajax({ cache: false, type: "POST", url: "/org/add_fav/", data: { fav_type: 2, fav_id: favid, csrfmiddlewaretoken: '799Y6iPeEDNSGvrTu3noBrO4MBLv6enY' }, async: true, success: function(data) { Dml.fun.winReload(); } }); }); </script> {% block custom_js %} {% endblock %}k %} <script> var shareUrl = '', shareText = '', shareDesc = '', shareComment = ''; $(function () { $(".bdsharebuttonbox a").mouseover(function () { var type = $(this).attr('data-cmd'), $parent = $(this).parent('.bdsharebuttonbox'), fxurl = $parent.attr('data-url'), fxtext = $parent.attr('data-text'), fxdesc = $parent.attr('data-desc'), fxcomment = $parent.attr('data-comment'); switch (type){ case 'tsina': case 'tqq': case 'renren': shareUrl = fxurl; shareText = fxdesc; shareDesc = ''; shareComment = ''; break; default : shareUrl = fxurl; shareText = fxtext; shareDesc = fxdesc; shareComment = fxcomment; break; } }); }); function SetShareUrl(cmd, config) { if (shareUrl) { config.bdUrl = "" + shareUrl; } if(shareText){ config.bdText = shareText; } if(shareDesc){ config.bdDesc = shareDesc; } if(shareComment){ config.bdComment = shareComment; } return config; } window._bd_share_config = { "common": { "onBeforeClick":SetShareUrl, "bdPic":"", "bdMini":"2", "searchPic":"1", "bdMiniList":false }, "share": { "bdSize":"16" } }; with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com../api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)]; </script> </body> </html>
(2)修改‘usercenter-info.html’继承usercenter-bae.html
{% load staticfiles %} <!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>{% block title %} 个人信息- 慕学在线网 {% endblock %}</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' %}"> <link rel="stylesheet" type="text/css" href="{% static 'js/plugins/queryCity/css/cityLayout.css' %}"> {% block custom_css %} {% endblock %} <link rel="stylesheet" type="text/css" href="{% static 'css/lq.datetimepick.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 headerwrap2"> <header> <div class="header2 header"> <div class="top"> <div class="wp"> <div class="fl"><p>服务电话:<b>33333333</b></p></div> <!--登录后跳转--> <div class="personal"> <dl class="user fr"> <dd>bobby<img class="down fr" src="{% static 'js/jquery-migrate-1.2.1.min.js' %}"/></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>bobby</p> </dd> </dl> <div class="btn"> <a class="personcenter fl" href="usercenter-info.html">进入个人中心</a> <a class="fr" href="/logout/">退出</a> </div> </div> </div> <a href="usercenter-message.html"> <div class="msg-num"><span id="MsgNum">0</span></div> </a> </div> </div> <div class="middle"> <div class="wp"> <a href="index.html"><img class="fl" src="{% static 'images/logo2.png' %}"/></a> <h1>我的慕学网</h1> </div> </div> </div> </header> </section> <!--crumbs start--> {% block custom_bread %} {% endblock %} <section> <div class="wp list personal_list"> <div class="left"> <ul> <li class="active2"><a href="usercenter-info.html">个人资料</a></li> <li ><a href="usercenter-mycourse.html">我的课程</a></li> <li ><a href="usercenter-fav-course.html">我的收藏</a></li> <li > <a href="usercenter-message.html" style="position: relative;"> 我的消息 </a> </li> </ul> </div> {% block custom_right_content %} {% endblock %} </div> </section> <!--sidebar start--> <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> <!--sidebar end--> <!--header start--> <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="bidtips dialogbox promptbox" id="jsComfirmDialig"> <h1>确认提交</h1> <div class="close jsCloseDialog"><img src="{% static 'images/dig_close.png' %}"/></div> <div class="cont"> <h2>您确认提交吗?</h2> <dd class="autoTxtCount"> <div class="button"> <input type="button" class="fl half-btn" value="确定" id="jsComfirmBtn"/> <span class="fr half-btn jsCloseDialog">取消</span> </div> </dd> </div> </div> <div class="resetpwdbox dialogbox" id="jsResetDialog"> <h1>修改密码</h1> <div class="close jsCloseDialog"><img src="{% static 'images/dig_close.png' %}"/></div> <div class="cont"> <form id="jsResetPwdForm" autocomplete="off"> <div class="box"> <span class="word2" >新 密 码</span> <input type="password" id="pwd" name="password1" placeholder="6-20位非中文字符"/> </div> <div class="box"> <span class="word2" >确定密码</span> <input type="password" id="repwd" name="password2" placeholder="6-20位非中文字符"/> </div> <div class="error btns" id="jsResetPwdTips"></div> <div class="button"> <input id="jsResetPwdBtn" type="button" value="提交" /> </div> {% csrf_token %} </form> </div> </div> <div class="dialogbox changeemai1 changephone" id="jsChangeEmailDialog"> <h1>修改邮箱</h1> <div class="close jsCloseDialog"><img src="{% static 'images/dig_close.png' %}"/></div> <p>请输入新的邮箱地址</p> <form id="jsChangeEmailForm" autocomplete="off"> <div class="box"> <input class="fl change_email" name="email" id="jsChangeEmail" type="text" placeholder="输入重新绑定的邮箱地址"> </div> <div class="box"> <input class="fl email_code" type="text" id="jsChangeEmailCode" name="code" placeholder="输入邮箱验证码"> <input class="getcode getting" type="button" id="jsChangeEmailCodeBtn" value="获取验证码"> </div> <div class="error btns change_email_tips" id="jsChangeEmailTips" >请输入...</div> <div class="button"> <input class="changeemai_btn" id="jsChangeEmailBtn" type="button" value="完成"/> </div> {% csrf_token %} </form> </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 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="forgetbox dialogbox"> <h1>忘记密码</h1> <div class="close jsCloseDialog"><img src="{% static 'images/dig_close.png' %}"/></div> <div class="cont"> <form id="jsFindPwdForm" autocomplete="off"> <div class="box"> <span class="word2" >账 号</span> <input type="text" id="account" name="account" placeholder="手机/邮箱"/> </div> <div class="box"> <span class="word3">验证码</span> <input autocomplete="off" class="form-control-captcha find-password-captcha" id="find-password-captcha_1" name="captcha_f_1" placeholder="请输入验证码" type="text" /> <input class="form-control-captcha find-password-captcha" id="find-password-captcha_0" name="captcha_f_0" placeholder="请输入验证码" type="hidden" value="5f3c00e47fb1be12d2fd15b9a860711597721b3f" /> <img src="/captcha/image/5f3c00e47fb1be12d2fd15b9a860711597721b3f/" alt="captcha" class="captcha" /> </div> <div class="error btns" id="jsForgetTips"></div><!--忘记密码错误--> <div class="button"> <input type="hidden" name="sms_type" value="1"> <input id="jsFindPwdBtn" type="button" value="提交" /> </div> </form> </div> </div> </div> <div class="bg" id="dialogBg"></div> <script src="{% static 'js/selectUi.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/validateDialog.js' %}" type="text/javascript"></script> <script src="{% static 'js/deco-common.js' %}" type="text/javascript"></script> <script src="{% static 'js/plugins/jquery.upload.js' %}" type='text/javascript'></script> <script src="{% static 'js/validate.js' %}" type="text/javascript"></script> <script src="{% static 'js/deco-user.js' %}"></script> <script type="text/javascript"> $('.jsDeleteFav_course').on('click', function(){ var _this = $(this), favid = _this.attr('data-favid'); alert(favid) $.ajax({ cache: false, type: "POST", url: "/org/add_fav/", data: { fav_type: 1, fav_id: favid, csrfmiddlewaretoken: '799Y6iPeEDNSGvrTu3noBrO4MBLv6enY' }, async: true, success: function(data) { Dml.fun.winReload(); } }); }); $('.jsDeleteFav_teacher').on('click', function(){ var _this = $(this), favid = _this.attr('data-favid'); $.ajax({ cache: false, type: "POST", url: "/org/add_fav/", data: { fav_type: 3, fav_id: favid, csrfmiddlewaretoken: '799Y6iPeEDNSGvrTu3noBrO4MBLv6enY' }, async: true, success: function(data) { Dml.fun.winReload(); } }); }); $('.jsDeleteFav_org').on('click', function(){ var _this = $(this), favid = _this.attr('data-favid'); $.ajax({ cache: false, type: "POST", url: "/org/add_fav/", data: { fav_type: 2, fav_id: favid, csrfmiddlewaretoken: '799Y6iPeEDNSGvrTu3noBrO4MBLv6enY' }, async: true, success: function(data) { Dml.fun.winReload(); } }); }); </script> {% block custom_js %} {% endblock %}k %} <script> var shareUrl = '', shareText = '', shareDesc = '', shareComment = ''; $(function () { $(".bdsharebuttonbox a").mouseover(function () { var type = $(this).attr('data-cmd'), $parent = $(this).parent('.bdsharebuttonbox'), fxurl = $parent.attr('data-url'), fxtext = $parent.attr('data-text'), fxdesc = $parent.attr('data-desc'), fxcomment = $parent.attr('data-comment'); switch (type){ case 'tsina': case 'tqq': case 'renren': shareUrl = fxurl; shareText = fxdesc; shareDesc = ''; shareComment = ''; break; default : shareUrl = fxurl; shareText = fxtext; shareDesc = fxdesc; shareComment = fxcomment; break; } }); }); function SetShareUrl(cmd, config) { if (shareUrl) { config.bdUrl = "" + shareUrl; } if(shareText){ config.bdText = shareText; } if(shareDesc){ config.bdDesc = shareDesc; } if(shareComment){ config.bdComment = shareComment; } return config; } window._bd_share_config = { "common": { "onBeforeClick":SetShareUrl, "bdPic":"", "bdMini":"2", "searchPic":"1", "bdMiniList":false }, "share": { "bdSize":"16" } }; with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com../api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)]; </script> </body> </html>
(3)配置urls
MxOnline/urls.py
#个人信息 path("users/", include('users.urls', namespace="users")),
users/urls.py
from django.urls import path,include,re_path from .views import UserinfoView app_name = 'users' urlpatterns = [ #用户信息 path("info/", UserinfoView.as_view(),name='user_info'), ]
users/views.py
class UserinfoView(LoginRequiredMixin,View): '''用户个人信息''' def get(self,request): return render(request,'usercenter-info.html',{})
然后访问http://127.0.0.1:8000/users/info/ 看看能不能正常显示
(4)显示个人信息
<ul class="right"> <li>昵 称: <input type="text" name="nick_name" id="nick_name" value="{{ request.user.nick_name }}" maxlength="10"> <i class="error-tips"></i> </li> <li>生 日: <input type="text" id="birth_day" name="birday" value="{{ request.user.birthday }}" readonly="readonly"/> <i class="error-tips"></i> </li> <li>性 别: <label> <input type="radio" name="gender" value="male" {% if request.user.gender == 'male' %}checked="checked"{% endif %}>男</label> <label> <input type="radio" name="gender" value="female" {% if request.user.gender == 'female' %}checked="checked"{% endif %}">女</label> </li> <li class="p_infor_city">地 址: <input type="text" name="address" id="address" placeholder="请输入你的地址" value="{{ request.user.adress }}" maxlength="10"> <i class="error-tips"></i> </li> <li>手 机 号: <input type="text" name="mobile" id="mobile" placeholder="请输入你的手机号码" value="{{ request.user.mobile|default_if_none:'' }}" maxlength="10"> </li> <li>邮 箱: <input class="borderno" type="text" name="email" readonly="readonly" value="{{ request.user.email }}"/> <span class="green changeemai_btn">[修改]</span> </li> <li class="button heibtn"> <input type="button" id="jsEditUserBtn" value="保存"> </li> </ul>
说明:
{{ request.user.mobile|default_if_none:'' }} 如果字段没有值,值默认为空字符串
11.2.修改用户图像
(1)url
#用户图像上传 path("image/upload", UploadImageView.as_view(),name='image_upload'),
(2)urers/forms.py
class UploadImageForm(forms.ModelForm): '''用户更改图像''' class Meta: model = UserProfile fields = ['image']
(3)views.py
class UploadImageView(LoginRequiredMixin,View): '''用户图像修改''' def post(self,request): #上传的文件都在request.FILES里面获取,所以这里要多传一个这个参数 image_form = UploadImageForm(request.POST,request.FILES) if image_form.is_valid(): image = image_form.cleaned_data['image'] request.user.image = image request.user.save() return HttpResponse('{"status":"success"}', content_type='application/json') else: return HttpResponse('{"status":"fail"}', content_type='application/json')
(4)前端页面
<iframe id='frameFile' name='frameFile' style='display: none;'></iframe>
<form class="clearfix" id="jsAvatarForm" enctype="multipart/form-data" autocomplete="off" method="post" action="{% url 'users:image_upload' %}" target='frameFile'> <label class="changearea" for="avatarUp"> <span id="avatardiv" class="pic"> <img width="100" height="100" class="js-img-show" id="avatarShow" src="{{ MEDIA_URL }}{{ request.user.image }}"/> </span> <span class="fl upload-inp-box" style="margin-left:70px;"> <span class="button btn-green btn-w100" id="jsAvatarBtn">修改头像</span> <input type="file" name="image" id="avatarUp" class="js-img-up"/> </span> </label> <input type='hidden' name='csrfmiddlewaretoken' value='799Y6iPeEDNSGvrTu3noBrO4MBLv6enY' /> {% csrf_token %} </form>
11.3.修改密码
(1)urls
#用户个人中心修改密码 path("update/pwd/", UpdatePwdView.as_view(),name='update_pwd'),
(2)后台处理
class UpdatePwdView(View): """ 个人中心修改用户密码 """ def post(self, request): modify_form = ModifyPwdForm(request.POST) if modify_form.is_valid(): pwd1 = request.POST.get("password1", "") pwd2 = request.POST.get("password2", "") if pwd1 != pwd2: return HttpResponse('{"status":"fail","msg":"密码不一致"}', content_type='application/json') user = request.user user.password = make_password(pwd2) user.save() return HttpResponse('{"status":"success"}', content_type='application/json') else: return HttpResponse(json.dumps(modify_form.errors), content_type='application/json')
(3)Ajxa代码放在deco-user.js里面
$(function(){ //个人资料修改密码 $('#jsUserResetPwd').on('click', function(){ Dml.fun.showDialog('#jsResetDialog', '#jsResetPwdTips'); }); $('#jsResetPwdBtn').click(function(){ $.ajax({ cache: false, type: "POST", dataType:'json', url:"", data:$('#jsResetPwdForm').serialize(), async: true, success: function(data) { if(data.password1){ Dml.fun.showValidateError($("#pwd"), data.password1); }else if(data.password2){ Dml.fun.showValidateError($("#repwd"), data.password2); }else if(data.status == "success"){ Dml.fun.showTipsDialog({ title:'提交成功', h2:'修改密码成功,请重新登录!', }); Dml.fun.winReload(); }else if(data.msg){ Dml.fun.showValidateError($("#pwd"), data.msg); Dml.fun.showValidateError($("#repwd"), data.msg); } } }); });
(4)修改右上角的登录个人状态
base.html
<header> <div class=" header"> <div class="top"> <div class="wp"> <div class="fl"><p>服务电话:<b>33333333</b></p></div> <!--登录后跳转--> {% if request.user.is_authenticated %} <div class="personal"> <dl class="user fr"> <dd>{{ user.username }}<img class="down fr" src="{% static "images/top_down.png" %}"/></dd> <dt><img width="20" height="20" src="{{ MEDIA_URL }}{{ request.user.image }}"/></dt> </dl> <div class="userdetail"> <dl> <dt><img width="80" height="80" src="{{ MEDIA_URL }}{{ request.user.image }}"/></dt> <dd> <h2>{{ request.user.nick_name }}</h2> <p>{{ request.user.username }}</p> </dd> </dl> <div class="btn"> <a class="personcenter fl" href="{% url 'users:user_info' %}">进入个人中心</a> <a class="fr" href="{% url 'logout' %}">退出</a> </div> </div> </div> {% else %} <a style="color:white" class="fr registerbtn" href="{% url 'register' %}">注册</a> <a style="color:white" class="fr loginbtn" href="{% url 'login' %}">登录</a> {% endif %} </div> </div>
同样的把org_base.html和user-center.html也修改一下
11.4.发送邮箱验证码
(1)EmailVerifyRecord Models
- 添加一个choices
- 把send_type的max_length改为30
send_choices = ( ('register','注册'), ('forget','找回密码'), ('update_email','修改邮箱') )
class EmailVerifyRecord(models.Model): send_choices = ( ('register','注册'), ('forget','找回密码'), ('update_email','修改邮箱') ) code = models.CharField('验证码',max_length=20) email = models.EmailField('邮箱',max_length=50) send_type = models.CharField(choices=send_choices,max_length=30) send_time = models.DateTimeField(default=datetime.now) class Meta: verbose_name = '邮箱验证码' verbose_name_plural = verbose_name
(2)url
#发送邮箱验证码 path("sendemail_code/", SendEmailCodeView.as_view(),name='sendemail_code'),
(3)view
class SendEmailCodeView(LoginRequiredMixin, View): '''发送邮箱修改验证码''' def get(self,request): email = request.GET.get('email','') if UserProfile.objects.filter(email=email): return HttpResponse('{"email":"邮箱已存在"}', content_type='application/json') send_register_eamil(email,'update_email') return HttpResponse('{"status":"success"}', content_type='application/json')
(4)urils/email_send.py
- 添加一个send_type update_email
- update_email的验证码长度为4
# apps/utils/email_send.py from random import Random from django.core.mail import send_mail from users.models import EmailVerifyRecord from MxOnline.settings import EMAIL_FROM # 生成随机字符串 def random_str(random_length=8): str = '' # 生成字符串的可选字符串 chars = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz0123456789' length = len(chars) - 1 random = Random() for i in range(random_length): str += chars[random.randint(0, length)] return str # 发送注册邮件 def send_register_eamil(email, send_type="register"): # 发送之前先保存到数据库,到时候查询链接是否存在 # 实例化一个EmailVerifyRecord对象 email_record = EmailVerifyRecord() # 生成随机的code放入链接 if send_type == 'update_email': code = random_str(4) else: code = random_str(16) email_record.code = code email_record.email = email email_record.send_type = send_type email_record.save() # 定义邮件内容: email_title = "" email_body = "" if send_type == "register": email_title = "NBA注册激活链接" email_body = "请点击下面的链接激活你的账号: http://127.0.0.1:8000/active/{0}".format(code) # 使用Django内置函数完成邮件发送。四个参数:主题,邮件内容,从哪里发,接受者list send_status = send_mail(email_title, email_body, EMAIL_FROM, [email]) # 如果发送成功 if send_status: pass elif send_type == "forget": email_title = "NBA找回密码链接" email_body = "请点击下面的链接找回你的密码: http://127.0.0.1:8000/reset/{0}".format(code) # 使用Django内置函数完成邮件发送。四个参数:主题,邮件内容,从哪里发,接受者list send_status = send_mail(email_title, email_body, EMAIL_FROM, [email]) # 如果发送成功 if send_status: pass elif send_type == "update_email": email_title = "NBA邮箱修改验证码" email_body = "你的邮箱验证码为{0}".format(code) # 使用Django内置函数完成邮件发送。四个参数:主题,邮件内容,从哪里发,接受者list send_status = send_mail(email_title, email_body, EMAIL_FROM, [email]) # 如果发送成功 if send_status: pass
(4)Ajax
Ajax代码在dec-user.js里面
//修改个人中心邮箱验证码 function sendCodeChangeEmail($btn){ var verify = verifyDialogSubmit( [ {id: '#jsChangeEmail', tips: Dml.Msg.epMail, errorTips: Dml.Msg.erMail, regName: 'email', require: true} ] ); if(!verify){ return; } $.ajax({ cache: false, type: "get", dataType:'json', url:"/users/sendemail_code/", data:$('#jsChangeEmailForm').serialize(), async: true, beforeSend:function(XMLHttpRequest){ $btn.val("发送中..."); $btn.attr('disabled',true); }, success: function(data){ if(data.email){ Dml.fun.showValidateError($('#jsChangeEmail'), data.email); }else if(data.status == 'success'){ Dml.fun.showErrorTips($('#jsChangeEmailTips'), "邮箱验证码已发送"); }else if(data.status == 'failure'){ Dml.fun.showValidateError($('#jsChangeEmail'), "邮箱验证码发送失败"); }else if(data.status == 'success'){ } }, complete: function(XMLHttpRequest){ $btn.val("获取验证码"); $btn.removeAttr("disabled"); } }); }
测试:
11.5.修改邮箱
(1)urls
#修改邮箱 path("update_email/", UpdateEmailView.as_view(),name='update_email'),
(2)view
class UpdateEmailView(LoginRequiredMixin, View): '''修改邮箱''' def post(self, request): email = request.POST.get("email", "") code = request.POST.get("code", "") existed_records = EmailVerifyRecord.objects.filter(email=email, code=code, send_type='update_email') if existed_records: user = request.user user.email = email user.save() return HttpResponse('{"status":"success"}', content_type='application/json') else: return HttpResponse('{"email":"验证码无效"}', content_type='application/json')
(3)Ajax
//个人资料邮箱修改 function changeEmailSubmit($btn){ var verify = verifyDialogSubmit( [ {id: '#jsChangeEmail', tips: Dml.Msg.epMail, errorTips: Dml.Msg.erMail, regName: 'email', require: true}, ] ); if(!verify){ return; } $.ajax({ cache: false, type: 'post', dataType:'json', url:"/users/update_email/ ", data:$('#jsChangeEmailForm').serialize(), async: true, beforeSend:function(XMLHttpRequest){ $btn.val("发送中..."); $btn.attr('disabled',true); $("#jsChangeEmailTips").html("验证中...").show(500); }, success: function(data) { if(data.email){ Dml.fun.showValidateError($('#jsChangeEmail'), data.email); }else if(data.status == "success"){ Dml.fun.showErrorTips($('#jsChangePhoneTips'), "邮箱信息更新成功"); setTimeout(function(){location.reload();},1000); }else{ Dml.fun.showValidateError($('#jsChangeEmail'), "邮箱信息更新失败"); } }, complete: function(XMLHttpRequest){ $btn.val("完成"); $btn.removeAttr("disabled"); } }); }
11.6.个人信息修改
(1)users/form.py
class UserInfoForm(forms.ModelForm): '''个人中心信息修改''' class Meta: model = UserProfile fields = ['nick_name','gender','birthday','address','mobile']
(2)view
class UserinfoView(LoginRequiredMixin,View): '''用户个人信息''' def get(self,request): return render(request,'usercenter-info.html') def post(self, request): user_info_form = UserInfoForm(request.POST, instance=request.user) if user_info_form.is_valid(): user_info_form.save() return HttpResponse('{"status":"success"}', content_type='application/json') else: return HttpResponse(json.dumps(user_info_form.errors), content_type='application/json')
11.7.我的课程
(1)url
#我的课程 path("mycourse/", MyCourseView.as_view(),name='mycourse'),
(2)view
class MyCourseView(LoginRequiredMixin, View): '''我的课程''' def get(self, request): user_courses = UserCourse.objects.filter(user=request.user) return render(request, "usercenter-mycourse.html", { "user_courses":user_courses, })
(3)usercenter-mucoure.html
{% extends 'usercenter-base.html' %} {% block title %} 我的课程 {% endblock %} {% block custom_bread %} <section> <div class="wp"> <ul class="crumbs"> <li><a href="{% url 'index' %}">首页</a>></li> <li><a href="/user/home/">个人中心</a>></li> <li>我的课程</li> </ul> </div> </section> {% endblock %} {% block custom_right_content %} <div class="right" > <div class="personal_des Releasecont"> <div class="head"> <h1>我的课程</h1> </div> </div> <div class="personal_des permessage"> <div class="companycenter"> <div class="group_list brief"> {% for user_course in user_courses %} <div class="module1_5 box"> <a href="{% url 'course:course_detail' user_course.course.id %}"> <img width="214" height="190" class="scrollLoading" src="{{ MEDIA_URL }}{{ user_course.course.image }}"/> </a> <div class="des"> <a href="course-detail.html"><h2>{{ user_course.course.name }}</h2></a> <span class="fl">课时:<i class="key">{{ user_course.course.learn_times }}</i></span> <span class="fr">学习人数:{{ user_course.course.students }}</span> </div> <div class="bottom"> <span class="fl">{{ user_course.course.course_org.name }}</span> <span class="star fr notlogin" data-favid="15">{{ user_course.course.fav_nums }}</span> </div> </div> {% endfor %} </div> </div> </div> </div> {% endblock %}
11.8.我的收藏--课程机构
(1)url
# 我的收藏--课程机构 path('myfav/org/', MyFavOrgView.as_view(), name="myfav_org"),
(2)view
class MyFavOrgView(LoginRequiredMixin,View): '''我收藏的课程机构''' def get(self, request): org_list = [] fav_orgs = UserFavorite.objects.filter(user=request.user, fav_type=2) # 上面的fav_orgs只是存放了id。我们还需要通过id找到机构对象 for fav_org in fav_orgs: # 取出fav_id也就是机构的id。 org_id = fav_org.fav_id # 获取这个机构对象 org = CourseOrg.objects.get(id=org_id) org_list.append(org) return render(request, "usercenter-fav-org.html", { "org_list": org_list, })
(3)模板usercenter-fav-org.html
{% extends 'usercenter-base.html' %} {% load staticfiles %} {% block title %} 我的收藏 {% endblock %} {% block custom_bread %} <section> <div class="wp"> <ul class="crumbs"> <li><a href="{% url 'index' %}">首页</a>></li> <li><a href="/user/home/">个人中心</a>></li> <li>我的收藏</li> </ul> </div> </section> {% endblock %} {% block custom_right_content %} <div class="right" > <div class="personal_des Releasecont"> <div class="head"> <h1>我的收藏</h1> </div> </div> <div class="personal_des permessage"> <div class="head"> <ul class="tab_header messagehead"> <li class="active"><a href="usercenter-fav-course.html">课程机构</a> </li> <li><a href="usercenter-fav-teacher.html">授课教师 </a></li> <li><a href="usercenter-fav-course.html">公开课程</a></li> </ul> </div> <div class="messagelist"> {% for org in org_list %} <div class="messages butler_list company company-fav-box"> <dl class="des fr"> <dt> <a href="{% url 'org:org_home' org.id %}"> <img width="160" height="90" src="{{ MEDIA_URL }}{{ org.image }}"/> </a> </dt> <dd> <h1><a href="org-detail-homepage.html">{{ org.name }}</a></h1> <div class="pic fl" style="width:auto;"> <img src="{% static 'images/authentication.png' %}"/> <img src="{% static 'images/gold.png' %}"/> </div> <span class="c8 clear">{{ org.address }}</span> <div class="delete jsDeleteFav_org" data-favid="{{org.id}}"></div> </dd> </dl> </div> {% endfor %} </div> </div> </div> {% endblock %}
11.9.我的收藏--授课讲师
Teacher添加一个方法
def get_course_nums(self): return self.course_set.all().count()
url,view和模板
# 我的收藏--授课讲师 path('myfav/teacher/', MyFavTeacherView.as_view(), name="myfav_teacher"),
class MyFavTeacherView(LoginRequiredMixin, View): '''我收藏的授课讲师''' def get(self, request): teacher_list = [] fav_teachers = UserFavorite.objects.filter(user=request.user, fav_type=3) for fav_teacher in fav_teachers: teacher_id = fav_teacher.fav_id teacher = Teacher.objects.get(id=teacher_id) teacher_list.append(teacher) return render(request, "usercenter-fav-teacher.html", { "teacher_list": teacher_list, })
{% extends 'usercenter-base.html' %} {% load staticfiles %} {% block title %} 我的收藏 {% endblock %} {% block custom_bread %} <section> <div class="wp"> <ul class="crumbs"> <li><a href="{% url 'index' %}">首页</a>></li> <li><a href="/user/home/">个人中心</a>></li> <li>我的收藏</li> </ul> </div> </section> {% endblock %} {% block custom_right_content %} <div class="right" > <div class="personal_des Releasecont"> <div class="head"> <h1>我的收藏</h1> </div> </div> <div class="personal_des permessage"> <div class="head"> <ul class="tab_header messagehead"> <li ><a href="{% url 'users:myfav_org' %}">课程机构</a> </li> <li class="active"><a href="{% url 'users:myfav_teacher' %}">授课教师 </a></li> <li><a href="usercenter-fav-course.html">公开课程</a></li> </ul> </div> <div class="messagelist"> {% for teacher in teacher_list %} <div class=" butler_list butler-fav-box"> <dl class="des users"> <dt> <a href="{% url 'org:teacher_detail' teacher.id %}"> <img width="100" height="100" src="{{ MEDIA_URL }}{{ teacher.image }}"/> </a> </dt> <dd> <h1> <a href="{% url 'org:teacher_detail' teacher.id %}"> {{ teacher.name }}<span class="key">认证教师</span> </a> </h1> <ul class="cont clearfix"> <li class="time">工作年限:<span>{{ teacher.work_years }}年</span></li> <li class="c7">课程数:<span>{{ teacher.get_course_nums }}</span></li> </ul> <ul class="cont clearfix"> <li class="time">工作公司:<span>{{ teacher.work_company }}</span></li> <li class="c7">公司职位:<span>{{ teacher.work_position }}</span></li> </ul> </dd> <div class="delete jsDeleteFav_teacher" data-favid="{{teacher.id}}"></div> </dl> </div> {% endfor %} </div> </div> </div> {% endblock %}
11.10.我的收藏--公开课程
#我的收藏--课程 path('myfav/course/', MyFavCourseView.as_view(), name="myfav_course"),
class MyFavCourseView(LoginRequiredMixin,View): """ 我收藏的课程 """ def get(self, request): course_list = [] fav_courses = UserFavorite.objects.filter(user=request.user, fav_type=1) for fav_course in fav_courses: course_id = fav_course.fav_id course = Course.objects.get(id=course_id) course_list.append(course) return render(request, 'usercenter-fav-course.html', { "course_list":course_list, })
{% extends 'usercenter-base.html' %} {% load staticfiles %} {% block title %} 我的收藏 {% endblock %} {% block custom_bread %} <section> <div class="wp"> <ul class="crumbs"> <li><a href="{% url 'index' %}">首页</a>></li> <li><a href="/user/home/">个人中心</a>></li> <li>我的收藏</li> </ul> </div> </section> {% endblock %} {% block custom_right_content %} <div class="right" > <div class="personal_des Releasecont"> <div class="head"> <h1>我的收藏</h1> </div> </div> <div class="personal_des permessage"> <div class="head"> <ul class="tab_header messagehead"> <li ><a href="{% url 'users:myfav_org' %}">课程机构</a> </li> <li ><a href="{% url 'users:myfav_teacher' %}">授课教师 </a></li> <li class="active"><a href="{% url 'users:myfav_course' %}">公开课程</a></li> </ul> </div> <div class="companycenter"> <div class="group_list brief"> {% for fav_course in course_list %} <div class="module1_5 box"> <a href="{% url 'course:course_detail' fav_course.id %}"> <img width="214" height="190" src="{{ MEDIA_URL }}{{ fav_course.image }}"/> </a> <div class="des"> <a href="{% url 'course:course_detail' fav_course.id %}"><h2>{{ fav_course.name }}</h2></a> <span class="fl">时长:<i class="key">{{ fav_course.learn_times }}</i></span> <span class="fr">学习人数:{{ fav_course.students }}</span> </div> <div class="bottom"> <span class="fl">{{ fav_course.course_org.name }}</span> <span class="delete-group fr jsDeleteFav_course" data-favid="{{fav_course.id}}"></span> </div> </div> {% endfor %} </div> </div> </div> </div> {% endblock %}
11.11.我的消息
(1)url
#我的消息 path('my_message/', MyMessageView.as_view(), name="my_message"),
(2)view
class MyMessageView(LoginRequiredMixin, View): '''我的消息''' def get(self, request): all_message = UserMessage.objects.filter(user= request.user.id) try: page = request.GET.get('page', 1) except PageNotAnInteger: page = 1 p = Paginator(all_message, 4,request=request) messages = p.page(page) return render(request, "usercenter-message.html", { "messages":messages, })
(3)模板 usercenter-message.html
{% extends 'usercenter-base.html' %} {% load staticfiles %} {% block title %} 我的消息 {% endblock %} {% block custom_bread %} <section> <div class="wp"> <ul class="crumbs"> <li><a href="{% url 'index' %}">首页</a>></li> <li><a href="/user/home/">个人中心</a>></li> <li>我的消息</li> </ul> </div> </section> {% endblock %} {% block custom_right_content %} <div class="right" > <div class="personal_des Releasecont"> <div class="head"> <h1>我的消息</h1> </div> </div> <div class="personal_des permessage"> <div class="head"> <ul class="tab_header messagehead"> <li class="active"><a href="/user/message/">个人消息</a> </li> </ul> </div> <div class="messagelist"> {% for message in messages.object_list %} <div class="messages"> <div class="fr"> <div class="top"><span class="fl time">{{ message.add_time }}</span><span class="fr btn foldbtn"></span></div> <p> {{ message.message }} </p> </div> </div> {% endfor %} </div> <div class="pageturn pagerright"> <ul class="pagelist"> {% if messages.has_previous %} <li class="long"><a href="?{{ messages.previous_page_number.querystring }}">上一页</a></li> {% endif %} {% for page in messages.pages %} {% if page %} {% ifequal page messages.number %} <li class="active"><a href="?{{ page.querystring }}">{{ page }}</a></li> {% else %} <li><a href="?{{ page.querystring }}" class="page">{{ page }}</a></li> {% endifequal %} {% else %} <li class="none"><a href="">...</a></li> {% endif %} {% endfor %} {% if messages.has_next %} <li class="long"><a href="?{{ messages.next_page_number.querystring }}">下一页</a></li> {% endif %} </ul> </div> </div> </div> {% endblock %}
11.12.logout
(1)url
path('logout/', LogoutView.as_view(), name="logout"),
(2)view
class LogoutView(View): '''用户登出''' def get(self,request): logout(request) from django.urls import reverse return HttpResponseRedirect(reverse('index'))
(3)在每个base页面添加链接
<a class="fr" href="{% url 'logout' %}">退出</a>
11.13.点击数
(1)课程 CourseInfoView
course.students += 1
course.save()
(2)TeacherDetailView
teacher.click_nums += 1
teacher.save()
(3)OrgHomeView
course_org.click_nums += 1
course_org.save()
11.14.收藏数
organization/views.py中的 AddFavView
减的时候
exist_record.delete() if int(type) == 1: course = Course.objects.get(id=int(id)) course.fav_nums -= 1 if course.fav_nums < 0: course.fav_nums = 0 course.save() elif int(type) == 2: org = CourseOrg.objects.get(id=int(id)) org.fav_nums -= 1 if org.fav_nums < 0: org.fav_nums = 0 org.save() elif int(type) == 3: teacher = Teacher.objects.get(id=int(id)) teacher.fav_nums -= 1 if teacher.fav_nums < 0: teacher.fav_nums = 0 teacher.save()
加的时候
user_fav.save() if int(type) == 1: course = Course.objects.get(id=int(id)) course.fav_nums += 1 course.save() elif int(type) == 2: org = CourseOrg.objects.get(id=int(id)) org.fav_nums += 1 org.save() elif int(type) == 3: teacher = Teacher.objects.get(id=int(id)) teacher.fav_nums += 1 teacher.save()
class AddFavView(View): """ 用户收藏和取消收藏 """ def post(self, request): id = request.POST.get('fav_id', 0) # 防止后边int(fav_id)时出错 type = request.POST.get('fav_type', 0) # 防止int(fav_type)出错 if not request.user.is_authenticated: # 未登录时返回json提示未登录,跳转到登录页面是在ajax中做的 return HttpResponse('{"status":"fail", "msg":"用户未登录"}', content_type='application/json') exist_record = UserFavorite.objects.filter(user=request.user, fav_id=int(id), fav_type=int(type)) if exist_record: # 如果记录已经存在,表示用户取消收藏 exist_record.delete() if int(type) == 1: course = Course.objects.get(id=int(id)) course.fav_nums -= 1 if course.fav_nums < 0: course.fav_nums = 0 course.save() elif int(type) == 2: org = CourseOrg.objects.get(id=int(id)) org.fav_nums -= 1 if org.fav_nums < 0: org.fav_nums = 0 org.save() elif int(type) == 3: teacher = Teacher.objects.get(id=int(id)) teacher.fav_nums -= 1 if teacher.fav_nums < 0: teacher.fav_nums = 0 teacher.save() return HttpResponse('{"status":"success", "msg":"收藏"}', content_type='application/json') else: user_fav = UserFavorite() if int(type) > 0 and int(id) > 0: user_fav.fav_id = int(id) user_fav.fav_type = int(type) user_fav.user = request.user user_fav.save() if int(type) == 1: course = Course.objects.get(id=int(id)) course.fav_nums += 1 course.save() elif int(type) == 2: org = CourseOrg.objects.get(id=int(id)) org.fav_nums += 1 org.save() elif int(type) == 3: teacher = Teacher.objects.get(id=int(id)) teacher.fav_nums += 1 teacher.save() return HttpResponse('{"status":"success", "msg":"已收藏"}', content_type='application/json') else: return HttpResponse('{"status":"fail", "msg":"收藏出错"}', content_type='application/json')
11.15.修改左侧active状态
usercenter-base.html
原始样子
<div class="left"> <ul> <li class="active2"><a href="{% url 'users:user_info' %}">个人资料</a></li> <li><a href="{% url 'users:mycourse' %}">我的课程</a></li> <li><a href="{% url 'users:myfav_org' %}">我的收藏</a></li> <li> <a href="{% url 'users:my_message' %}" style="position: relative;"> 我的消息 </a> </li> </ul> </div>
修改为
<div class="left"> <ul> <li {% ifequal '/users/info/' request.path %} class="active2" {% endifequal %}><a href="{% url 'users:user_info' %}">个人资料</a></li> <li {% ifequal '/users/mycourse/' request.path %} class="active2" {% endifequal %}><a href="{% url 'users:mycourse' %}">我的课程</a></li> <li {% ifequal '/users/myfav/' request.path|slice:'13' %} class="active2" {% endifequal %}><a href="{% url 'users:myfav_org' %}">我的收藏</a></li> <li {% ifequal '/users/my_message/' request.path %} class="active2" {% endifequal %}> <a href="{% url 'users:my_message' %}" style="position: relative;"> 我的消息 </a> </li> </ul> </div>