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