Django笔记-详解判断用户是否登录的几种方式(is_authenticated,LoginRequired Mixin,login_required )

Django笔记-判断用户是否登录的几种方式

  • 一、需求

    当用户访问某些网页时(如用户中心),此时需要判断用户是否登录,用户登录才能访问,未登录引导用户跳转至相应的网页或者返回相应数据。

  • 二、通过request.user.is_authenticated验证用户是否登录

    1、is_authenticated方法说明:
    is_authenticated 属于Django User对象中的一个方法,只是Django在内部通过装饰器@property将该方法装饰为可被User对象调用的一个属性。

    在这里插入图片描述

    2.is_authenticated方法的实现过程:
    用户在登录过后,Django会将用户的id以及use_backen写入到session会话,以一定的有效期存入数据库或者缓存中。并在登录响应cookie中写入一个sessionid=xxxxxxxxx的值。当用户访问用户中心(或其他需要登录才能访问的页面时),我们在视图中调用的request.user.is_authenticated方法就会去获取当前请求对象cookie中sessionid=xxxxx的值,然后通过’xxxx‘这个值去数据库或者缓存中找到当前这个’xxxx’值对应的记录值,然后判断用户登录或存在。

    3.返回值:True,False

    # 路由
    path('auth/', AuthenticatedView.as_view()),
    # 视图
    class AuthenticatedView(View):
        def get(self, request):
        	# 判断用户是否登录
            if not request.user.is_authenticated:
                return http.JsonResponse({
                    'errmsg': '用户未登录'
                })
            return http.JsonResponse({
                'errmsg': '登录成功',
            })
    
  • 三、通过继承LoginRequired Mixin类判断用户是否登录

    由于request.user.is_authenticated只返回true、false,每次我们都要编写未登录后的逻辑。这时可以使用LoginRequired Mixin自定义封装未登录后的业务逻辑代码。LoginRequired Mixin是处于django.contrib.auth.mixins中的一个类,它内部封装了调用了request.user.is_authenticated方法,那么未经验证用户的所有请求都会被重定向到登录页面或者显示 HTTP 403 Forbidden 错误
    在这里插入图片描述
    ![得分](https://img-blog.csdnimg.cn/403e0cedd23542f0825dfbf41be9e916.png

    这里我们可以继承至 LoginRequired Mixin类(确保继承至最左边),然后重写handle_no_permission方法,自定义返回相应的用户未登录操作,只要视图继承了该方法就会自动判断用户是否的登陆。

    # 封装
    class LoginJsondMixin(LoginRequiredMixin):
        def handle_no_permission(self):
            return http.JsonResponse({
                'errmsg': '用户未登录'
            })
    
    # 视图继承
    class AuthenticatedView(LoginRequiredMixin, View):
        def get(self, request):
            return http.JsonResponse({
                'errmsg': '登录成功',
            })
    
  • 四、基于(视图函数)通过login_required 装饰器判断用户是否登录

    login_required是位于django.contrib.auth.decorators下的一个装饰器,接受三个参数:
    1.function=None:
    -----------接受需要进行装饰的方法
    2.login_url=None:
    -----------如果未登录,会重定向到login_url参数传入url地址,默认为全局配置文件下的配置项LOGIN_URL的值
    3.redirect_field_name=REDIRECT_FIELD_NAME :
    -----------REDIRECT_FIELD_NAME默认为next,该参数的作用是未登录用户访问当前被login_required装饰的视图函数时,那么会在login_url地址的后面加上?next=‘当前视图函数的路由’
    4.例如:
    -----------当前视图函数的路由为userinfo/,login_url=’/login‘,redirect_field_name=’next,那么在用户未登录的情况下访问该视图,login_required会重定向到/login/?next=/userinfo/

    小案例测试login_required:

    1).模板:index(首页),login(登录),userinfo(用户中心):

    index:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
    <div>
        <h1>首页</h1>
        <a href="/userinfo">用户中心</a>
    </div>
    </body>
    </html>
    

    login:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>登录</title>
    </head>
    <body>
        <form id='app' method="post">
            <label for="">用户名:</label><input type="text" name="username"></br>
            <label for="">密码:</label><input type="password" name="password"></br>
            <input type="submit" value="登录" >
        </form>
    </body>
    </html>
    

    userinfo

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>用户中心</title>
    </head>
    <body>
        <div>
            <h1>hello {{ username }}</h1>
        </div>
    </body>
    </html>
    

    2).路由:

    from django.urls import re_path, path
    from users.views import *
    
    
    urlpatterns = [
        path('login/', Login),
        path('userinfo/', userinfo),
        path('index/', index)
    ]
    

    3).视图: Login(),userinfo(),indxe()

    # Create your views here.
    # 首页视图
    def index(requset):
        return render(requset, template_name='index.html')
    
    # 登录视图
    def Login(request):
        """
        测试login_required
        """
        if request.method == 'GET':
            return render(request, template_name='login.html')
        elif request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            if not all([username, password]):
                return http.JsonResponse({
                    'errmsg': '缺少必传参数'
                })
            # 验证用户
            user = authenticate(username=username, password=password)
            if user is None:
                return http.JsonResponse({
                    'errmsg': '密码错误'
                })
            # 登录用户
            login(request, user)
            
            next = request.GET.get('next')
            if next:  # 判断是否有next查询字符串,如果有的话登录成功跳转到next对应的地址
                response = redirect(next)
            else:  # 否则跳转到首页
                response = redirect('/index')
            # 设置cookies
            response.set_cookie('username', username, max_age=settings.SESSION_COOKIE_AGE)
            return response
        else:
            return http.JsonResponse({
                'errmsg': '不支持此请求'
            })
    
    # 对userinfo进行装饰,未登录用户跳转到登录视图(/login/?next=/userinfo/),
    @login_required(login_url='/login')
    def userinfo(request):
        if request.method == 'GET':
            username = request.COOKIES.get('username')
            context = {
                'username': username
            }
            return render(request, template_name='userinfo.html', context=context)
    

    4)效果图:
    在这里插入图片描述
    在这里插入图片描述
    这里登录时,登录视图函数会判断是否存在next查询字符串,有的话则跳转到相应的地址,没有的话跳转到index

  • 五、基于视图基类(View)通过login_required 装饰器判断用户是否登录
    1.在配置路由时使用login_required

    login_required装饰器在上面提到装饰的是一个函数,我们定义的视图函数也是一个函数,那么当我们的视图是基于视图基类View写的话,
    那么我们使用login_required装饰器就会发生改变,如下:
    视图类:
    在这里插入图片描述
    匹配的路由规则(参数一:路径,参数二:可调用对象(即视图函数)):
    在这里插入图片描述
    因为我们的类继承至视图基类View,在View类里面为我们提供了一个方法as_view(),返回了一个可被调用的对象函数(view),所以我们这里可以通过在配置路由时,用login_required装饰对应自定义的视图类.as_view()。对于View的原理分析可以查看https://www.zmrenwu.com/courses/django-class-based-views-source-code-analysis/materials/37/#as_view

    2、通过封装as_view函数使用login_required

    这里我们自己编写一个类LoginRequired,定义一个类方法as_view,调用View.as_view()方法得到一个函数对象view,通过login_required装饰后返回,接着在自己编写的视图上继承LoginRequired、View,由于多继承的关系,要确保LoginRequired在最左边,这时我们在编写路由时通过LoginRequiredView调用到的就是我们自己编写的as_view()函数,返回的就是已经被装饰后的viw函数对象。并且也具备视图基类View的功能

    path('loginrequired/', LoginRequiredView.as_view())
    
    class LoginRequired(object):
        @classmethod
        def as_view(cls, **initkwargs):
            # 自定义as_view()方法中,调用父类的as_view()方法
            view = super().as_view()
            return login_required(view)
        
        
    class LoginRequiredView(LoginRequired, View):
        def get(self, request):
            return http.JsonResponse({
                'errmsg': 'ok'
            })
    

    大概就是以上这样,有不理解或者不对的地方,可以下方留言一起探讨!!
    上一篇-Django实现用户退出登录(logout):https://blog.csdn.net/adminwg/article/details/126196630

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值