您的当前位置:首页正文

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

2024-11-30 来源:个人技术集锦

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

    这里我们可以继承至 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:

    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)效果图:

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

    login_required装饰器在上面提到装饰的是一个函数,我们定义的视图函数也是一个函数,那么当我们的视图是基于视图基类View写的话,
    那么我们使用login_required装饰器就会发生改变,如下:
    视图类:

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

显示全文