关于本站
1、基于Django+Bootstrap开发
2、主要发表本人的技术原创博客
3、本站于 2015-12-01 开始建站
由于每个页面都需要显示登录和注册按钮,首先在菜单所在的模板加上这两个按钮。
<ul id="user_part" class="nav navbar-nav navbar-right"> <li><a href="#" data-toggle="modal" data-target="#LoginModal">登录</a></li> <li><a href="#" data-toggle="modal" data-target="#RegModal">注册</a></li> </ul>
这里我使用了Bootstrap框架的弹窗功能。这两个按钮分别绑定到id为LoginModal和RegModal元素上面。html代码如下:
<!-- 登录模态框(Modal) --> <div style="display: none;" class="modal fade" id="LoginModal" tabindex="-1" role="dialog" aria-labelledby="LoginModalLabel" aria-hidden="true"> <div class="modal-dialog modal-sm"> <div class="modal-content"> <form id="login_form" action="/user/user_login" method="POST"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true"> × </button> <h4 class="modal-title" id="LoginModalLabel"> 登录 <small>是一种态度</small> </h4> </div> <div class="modal-body" style="text-align:center;"> <div class="control-group"> <label class="control-label" for="login_name">邮箱:</label> <input id="login_name" class="input-xlarge" name="login_name" placeholder="请输入邮箱" autocomplete="off" type="text"> </div> <div class="control-group"> <label class="control-label" for="login_pwd">密码:</label> <input id="login_pwd" class="input-xlarge" name="login_pwd" placeholder="请输入密码" autocomplete="off" type="password"> </div> <p id="login_tip" style="color:red;"></p> </div> <div class="modal-footer"> <input class="btn btn-primary" value="登录" type="submit"> <input class="btn btn-default" data-dismiss="modal" value="关闭" type="button"> </div> </form> </div><!-- /.modal-content --> </div><!-- /.modal --> </div> <!-- 注册模态框(Modal) --> <div class="modal fade" id="RegModal" tabindex="-1" role="dialog" aria-labelledby="RegModalLabel" aria-hidden="true"> <div class="modal-dialog modal-sm"> <div class="modal-content"> <form id="reg_form" action="#" method="POST"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true"> × </button> <h4 class="modal-title" id="RegModalLabel"> 注册 <small>是新的开始</small> </h4> </div> <div class="modal-body" style="text-align:center;"> <div id="reg_control"> <div class="control-group"> <label class="control-label" for="reg_name">邮箱:</label> <input id="reg_name" class="input-xlarge" name="reg_name" placeholder="请输入邮箱" autocomplete="off" type="text"> </div> <div class="control-group"> <label class="control-label" for="reg_pwd">密码:</label> <input id="reg_pwd" class="input-xlarge" name="reg_pwd" placeholder="请输入密码" autocomplete="off" type="password"> </div> </div> <p id="reg_tip" style="color:red;"></p> </div> <div class="modal-footer"> <input class="btn btn-primary" value="注册" type="submit"> <input class="btn btn-default" data-dismiss="modal" value="关闭" type="button"> </div> </form> </div><!-- /.modal-content --> </div><!-- /.modal --> </div>
这个默认设置是不可见的,点了菜单对应的按钮就会自动弹窗显示,具体使用方法见Bootstrap的帮助文档。
前端页面先写到这里,接下来要先写后端,提供几个接口(检查是否登录,登录,登出)给前端使用。
在网站程序目录下,创建一个文件夹"user_ex",在里面添加一个__init__.py空文件代表这个是一个包。模仿其他应用添加urls.py文件和views.py文件。
接下来,分别配置网址路由和处理请求。
首先,如下设置添加网址配置,分别处理检查登录状态和登入、登出的请求。
from django.conf.urls import include, url #start with 'user/' urlpatterns = [ url(r'^check_is_login$','user_ex.views.check_is_login',name='check_is_login'), url(r'^user_logout$','user_ex.views.user_logout',name='user_logout'), url(r'^user_login$','user_ex.views.user_login',name='user_login'), ]
并在总的urls.py文件加载这个文件,修改最外层的urls.py文件
urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^favicon\.ico$', RedirectView.as_view(url='/static/media/favicon.ico')), url(r'^$','yshblog.views.home',name='home'), url(r'^blog/',include('blog.urls')), url(r'^tools/',include('tools.urls')), url(r'^tutorial/',include('tutorial.urls')), url(r'^user/',include('user_ex.urls')), #加载 user_ex包下的urls文件配置 ]
配置完成之后,接下来处理请求了。打开views.py文件,加入如下代码:
#coding:utf-8 from django.http import HttpResponse,HttpResponseRedirect from django.shortcuts import render_to_response from django.contrib.auth import logout,authenticate,login from django.contrib.auth.models import User #user model from django.core.urlresolvers import reverse #url逆向解析 from django.views.decorators.csrf import csrf_exempt import json def check_is_login(request): """check the user is logined""" if request.user.is_authenticated(): username=request.user.first_name if not username: username=request.user.username if request.user.is_active: active_state='' else: active_state=u'(未激活)' returnText=u''' <li role="presentation" class="dropdown"> <a class="dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false"> 您好,%s%s <span class="caret"></span> </a> <ul class="dropdown-menu"> <li><a href="%s">退出</a></li> </ul> </li>''' % (username,active_state,reverse('user_logout'))#用reverse逆向解析user_logout得到网址 else: #登录不成功就返回“登录”、“注册”的菜单 returnText=u''' <li><a href="#" data-toggle="modal" data-target="#LoginModal">登录</a></li> <li><a href="#" data-toggle="modal" data-target="#RegModal">注册</a></li>''' return HttpResponse(returnText, content_type='application/javascript') def user_logout(request): """logout""" logout(request) #记住来源的url,如果没有则设置为首页('/') returnPath=request.META.get('HTTP_REFERER', '/') #重定向到原来的页面,相当于刷新 return HttpResponseRedirect(returnPath) #由于用ajax提交,设置不到csrf,就先不进行csrf验证 @csrf_exempt def user_login(request): """login""" response_data = {} try: login_name = request.POST.get('login_name') login_pwd = request.POST.get('login_pwd') if len(login_name)*len(login_pwd)==0: raise Exception(u"邮箱或密码为空") #判断是否正确 user = authenticate(username=login_name, password=login_pwd) if user is not None: login(request, user)#登录 else: raise Exception(u"邮箱或密码不正确") response_data['success'] = True response_data['message'] = 'ok' except Exception as e: response_data['success'] = False response_data['message'] = e.message finally: #返回json数据 return HttpResponse(json.dumps(response_data), content_type="application/json")
看起来代码有点多,实际上逻辑不复杂,基本上都是验证数据再处理数据。
里面涉及到url逆向解析,auth登入登出,返回json数据等,大家可以参考一下。有些东西写起来比较多,后面有时间我在把这个Django网站制作录制成视频教程。
其中message.html模版是显示消息的,可以参考我的网站搭建(第13天) 用户认证:前言博文的末尾。
到这里之后,还差一步。就是前端用ajax提交数据了。回过头修改一下前端的文件(同样是菜单所在的模板)把代码加在function(){}中,这样页面加载就会执行这些代码。
//检查登录状态 $.ajax({ type:"GET", url:"{% url 'check_is_login' %}", cache:false, dataType:'text', success:function(result){ $("#user_part").html(result); }, error:function(XMLHttpRequest, textStatus, errorThrown){ //alert(textStatus); $("#user_part").html('<li><a href="#" data-toggle="modal" data-target="#LoginModal">登录</a></li><li><a href="#" data-toggle="modal" data-target="#RegModal">注册</a></li>'); } }); //登录 $('#login_form').submit(function(){ //验证 var tip=$('#login_tip'); tip.text(''); if($('#login_name').val()==''){ tip.text('请输入邮箱'); return false; }; if($('#login_pwd').val()==''){ tip.text('请输入密码'); return false; }; //登录 $('#login_csrf').val($.cookie('csrftoken')); $.ajax({ type: "POST", data: $('#login_form').serialize(), url: "{% url 'user_login' %}", cache: false, dataType: "json", success: function(json, textStatus){ var is_success = json['success']; if(is_success){ tip.text('登录成功,页面处理中...'); window.location.reload(); }else{ tip.text('邮箱或者密码错误,请重试'); }; }, error: function (XMLHttpRequest, textStatus, errorThrown) { tip.text("登录出错,请重试 "+errorThrown); } }); return false; });
到这里就完成了检查登录状态、登入和登出这三个功能。另外测试发现会有点闪动的现象,去掉最前面写的登录注册菜单里面的内容即可。
<ul id="user_part" class="nav navbar-nav navbar-right"></ul>
Camberwell
不知道为啥这里的ajax form提交一直失败,一点登陆就跳转到 /user/user_login 页面了。。。。😭
2018-04-23 13:12 回复
Camberwell
谢谢博主解答,我这里好像是 ajax 的 csrf 验证有问题,自己手动加了 csrf 验证的上下文就好了。
2018-05-07 12:43 回复