Django 使用login函数登陆和注销

一、登陆

1、写一个简单的登陆页面,如下


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录title>
head>
<body>
<form action="" method="POST">
    <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
    <table>
        <tbody>
            <tr>
                <td>用户名:td>
                <td><input type="text" name="username">td>
            tr>
            <tr>
                <td>密码:td>
                <td><input type="password" name="password">td>
            tr>
            <tr>
                <td>
                    <label for="">
                        <input type="checkbox" name="remember" value="1">记住我
                    label>
                td>
                <td>td>
            tr>
            <tr>
                <td>td>
                <td><input type="submit" value="登录">td>
            tr>
        tbody>
    table>
form>
body>
html>

Django 使用login函数登陆和注销_第1张图片
2、定义一个登陆的视图函数

from django.contrib.auth import login,logout
from django.contrib.auth.decorators import login_required,permission_required
# 切记:这里一定不要定义login视图函数,可以其他的名字
def my_login(request):
    #如果是GET请求则直接返回页面
    if request.method == 'GET':
        return render(request,'login.html')
    #如果是POST请求则获取用户名、密码等
    else:
        username = request.POST.get('username')
        password = request.POST.get('password')
        remember = request.POST.get('remember')
        #使用Django自带的authenticat()函数判断是否有该用户
        user = authenticate(username=username,password=password)
        #如果存在该用户并且状态是激活的
        if user and user.is_active:
            #使用Django的login()函数进行登陆
            login(request,user)
            #如果记住登陆,则使用全局的过期时间,默认为2周
            if remember:
                # 设置为None,则表示使用全局的过期时间
                request.session.set_expiry(None)
            else:
                #否则设为0,关掉浏览器就注销登陆状态了
                request.session.set_expiry(0)
            #获取next页面(原本要访问的页面,因为没登陆所以转到login页面了),如果有的话则重定向到该页面
            next_url = request.GET.get('next')
            if next_url:
                return redirect(next_url)
            else:
                return HttpResponse('登录成功')
        else:
            return HttpResponse('用户名或密码错误!')

3、添加路由

path('login/',views.my_login,name='login')

4、输入账号密码登陆
Django 使用login函数登陆和注销_第2张图片
5、登陆成功
Django 使用login函数登陆和注销_第3张图片
查看cookies,有一个sessionid,这里的过期时间为N/A,因为没选择记住
在这里插入图片描述
如果选择记住,即remember为True,使用默认的全局过期时间,为2周
在这里插入图片描述
6、一个异常
如果之前有对user表做修改或外键的话,可能会遇到django.contrib.auth.models.User.extension.RelatedObjectDoesNotExist这样的异常,我遇到的情况是因为使用了外键,但是原本user表中已经创建了没有外键关联的用户,但写了一个接受保存模型的信号处理方法,会监听原本User模型的操作,这样导致如果用User模型中没有外键关联的用户登录的话,报不存在错误DestNotExist。所以如果不打算使用默认的User模型的话,一开始就需要修改好,不要创建了用户再去修改,会产生一些异常。
这里我在UserExtension模型监听User模型的方法中捕捉这个异常然后pass了

@receiver(post_save,sender=User)
def handler_user_extension(sender,instance,created,**kwargs):
    if created:
        UserExtension.objects.create(user=instance)
    else:
        try:
            instance.extension.save()
        except User.extension.RelatedObjectDoesNotExist:
            pass

7、函数功能介绍

login()函数根据用户信息,生成sessionid,这个sessionid是必须保存在数据库当中的,因为需要在用户登陆后,查询session,取出用户基本信息(session_data)

  • session_key:服务器返回给用户的sessionid
  • session_data:一段加密的文字,把用户的信息生成一段经过加密的字符串。
  • expire_date:session过期时间
    Django 使用login函数登陆和注销_第4张图片

那么是如何把seesionid转换成user的?
是因为在setting.py中有个配置,如下图:在INSTALLED_APPS中有一个’django.contrib.sessions’APP,这个APP是会对每次request和response请求做拦截,拦截到浏览器过来的request的时候,就会在里面找到sessionid,找到sessionid之后,通过查询数据库,找到session_data,对数据进行解密,便可以直接把user取出来。
如果注释掉’django.contrib.sessions’,自动登录就会失效。
Django 使用login函数登陆和注销_第5张图片

  • 服务器第一次响应浏览器请求时,会生成一个sessionid,返回给浏览器;
  • 浏览器再次请求时,会带上cookie中的sessionid,服务器通过查询seesionid,在数据库中查询是哪个用户,取出信息,返回给浏览器;
  • Django就通过cookie和session机制完成了自动登录。

二、注销

logout函数只有一个参数,就是request。没有返回值,而且即使当前用户没有登陆也不会抛出任何异常。

1、定义一个注销登陆的视图函数

from django.contrib.auth import logout
def my_logout(request):
    logout(request)
    return HttpResponse('成功退出登录!')

2、访问注销的视图函数,此时cookies已经清除
Django 使用login函数登陆和注销_第6张图片

三、登录限制

1、有时候,某个视图函数是需要经过登录后才能访问的。那么我们可以通过django.contrib.auth.decorators.login_required装饰器来实现。示例代码如下:

from django.contrib.auth.decorators import login_required

# 在验证失败后,会跳转到/login/这个url页面
@login_required(login_url='/login/')
def profile(request):
    return HttpResponse('只有登陆后访问')
path('profile/',views.profile,name='profile')

2、然后访问这个视图函数http://127.0.0.1:8000/profile/
Django 使用login函数登陆和注销_第7张图片
3、输入账号密码后则可以访问到next页面
Django 使用login函数登陆和注销_第8张图片

4、login_required()装饰器函数做了以下事情:

如果当前用户没有登陆,跳转到settings.LOGIN_URL,并传递当前的绝对路径到URL请求参数中,例如:/accounts/login/?next=/polls/3/
如果当前用户已经登陆了,执行view方法。在view中的方法可以认为当前用户已经登陆了。

login_required方法接受两个参数:

  • redirect_field_name:默认值是next。用来定义登陆成功之后的跳回之前访问界面的url。
  • login_url:默认值是settings.LOGIN_URL。用来指定登陆界面的url。如果不传入改参数,就需要确保settings.LOGIN_URL的值是正确设置的。默认是/accounts/login

四、总结

大概就写这些吧,关于cookies和session可以看前面写的一篇博客
https://blog.csdn.net/qq_41475058/article/details/103992833
如果没用django的login函数进行登陆验证的话,感觉不是很方便,还得自己写认证方法和装饰器,而且session还涉及到加密解密,所以上面这篇里的登陆验证方法主要就是了解一下登陆验证的一个原理,还是使用django的login比较方便。

关于User模型的可以看上一篇博客
https://blog.csdn.net/qq_41475058/article/details/104480987

参考:https://www.cnblogs.com/wangwei916797941/p/7398962.html
https://www.jianshu.com/p/70f19cae1d38

你可能感兴趣的:(Django)