关于本站
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 回复