我的网站搭建(第14天) 登入和登出

  • 发布时间:2016年3月22日 22:13
  • 作者:杨仕航
* 该文是基于Python2.7开发的,最新Python3.x和Django2.x视频教程可以前往 >> Django2.0视频教程

由于每个页面都需要显示登录和注册按钮,首先在菜单所在的模板加上这两个按钮。

<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>

上一篇:我的网站搭建(第15天) 注册认证

下一篇:我的网站搭建(第13天) 用户认证:前言

评论列表

Camberwell

Camberwell

不知道为啥这里的ajax form提交一直失败,一点登陆就跳转到 /user/user_login 页面了。。。。😭

2018-04-23 13:12 回复

Camberwell

Camberwell

谢谢博主解答,我这里好像是 ajax 的 csrf 验证有问题,自己手动加了 csrf 验证的上下文就好了。

2018-05-07 12:43 回复

新的评论

清空