Django中验证是否用户登陆的方式

最近一直在做在线学习系统,其中好多功能必须是用户登录以后才能执行的,比如查看个人信息,比如点击我要学习,或者我要收藏等等。

那么Django重验证用户登录的方式有几种呢?这里来汇总下。

使用is_authenticated()函数

这个函数就是验证是否用户登录,写在每个需要验证的视图函数中,举个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class CourseDetailView(View):
def get(self, request, course_id):
all_courses = Course.objects.all()
...
if request.user.is_authenticated():
if UserFavor.objects.filter(user= request.user, fav_id=cur_course.id, fav_type=1):
has_course_fav = True
# 判断课程所属培训机构是否已经被收藏
has_org_fav = False
if request.user.is_authenticated():
if UserFavor.objects.filter(user= request.user,
...
return render(request,"course-detail.html",{
'course':cur_course,
'has_org_fav':has_org_fav,
...
})

函数is_authenticated()的源码:

1
# 明天再给添上

这个视图函数对应的是讲师详情的页面,这个页面上有两个收藏的按钮,一个是收藏当前页面的讲师,另一个是收藏这个讲师对应的培训机构,再点击收藏的按钮的时候,需要获取当前的用户信息,所以要求用户是登录的状态,所以在进入收藏的逻辑之前要先验证用户是否是登录状态,如果是,就进入下面的逻辑,如果不是就需要跳转到登录页面登录。

其实在用户未登录的状态下,Django会自动设置一个虚拟的request.user,因为是虚拟的,所以不能使用request.user.is_authenticated()这个方法。


使用自己定义的mixin_utils.py

我们可以在util中自定义一个用于验证用户是否登录的类,每个需要用户登录后才能进行的操作,我们都要继承于这个类,下面是mixin_utils.py

1
2
3
4
5
6
7
8
9
10
from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator
# 自己定义验证用户是否登录的视图函数
class LoginRequiredMixin(object):
@method_decorator(login_required(login_url='/users/login/'))
def dispatch(self, request, *args, **kwargs):
return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)

这里我们使用了装饰器@method_decorator

course/views.py中,每次用户点击我要学习都必须是登录的状态,所以需要这样写:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from utils.mixin_utils import LoginRequiredMixin
# 课程详情
class CourseDetailView(LoginRequiredMixin, View):
def get(self, request, course_id):
# 获取当前的课程
...
return render(request,"course-detail.html",{
'course':cur_course,
'has_org_fav':has_org_fav,
'has_course_fav':has_course_fav,
'all_lessons': all_lessons,
'lesson_mun': lesson_num,
'cur_course_org': cur_course_org,
'reco_courses': reco_courses,
})


使用Django自带的装饰器@login_required

Django自带了一个装饰器@login_required,这个装饰器是用来验证用户是否登录。

下面介绍下这个装饰器的用法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from django.contrib.auth.decorators import login_required
# 课程详情
class CourseDetailView(View):
@login_required
def get(self, request, course_id):
# 获取当前的课程
...
return render(request,"course-detail.html",{
'course':cur_course,
'has_org_fav':has_org_fav,
'has_course_fav':has_course_fav,
'all_lessons': all_lessons,
'lesson_mun': lesson_num,
'cur_course_org': cur_course_org,
'reco_courses': reco_courses,
})

login_required()完成下面的事情:

  • 如果用户没有登入,则重定向到settings.LOGIN_URL,并将当前访问的绝对路径传递到查询字符串中。例如:/accounts/login/?next=/polls/3/。

  • 如果用户已经登入,则正常执行视图。视图的代码可以安全地假设用户已经登入。

默认情况下,在成功认证后用户应该被重定向的路径存储在查询字符串的一个叫做”next”的参数中。如果对该参数你倾向使用一个不同的名字,login_required()带有一个可选的redirect_field_name参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from django.contrib.auth.decorators import login_required
# 课程详情
class CourseDetailView(View):
@login_required(redirect_field_name='my_redirect_field')
def get(self, request, course_id):
# 获取当前的课程
...
return render(request,"course-detail.html",{
'course':cur_course,
'has_org_fav':has_org_fav,
'has_course_fav':has_course_fav,
'all_lessons': all_lessons,
'lesson_mun': lesson_num,
'cur_course_org': cur_course_org,
'reco_courses': reco_courses,
})

注意,如果你提供一个值给redirect_field_name,你非常可能同时需要自定义你的登录模板,因为存储重定向路径的模板上下文变量将使用redirect_field_name值作为它的键,而不是默认的next

login_required()还带有一个可选的login_url参数。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from django.contrib.auth.decorators import login_required
# 课程详情
class CourseDetailView(View):
@login_required(login_url='/users/login/')
def get(self, request, course_id):
# 获取当前的课程
...
return render(request,"course-detail.html",{
'course':cur_course,
'has_org_fav':has_org_fav,
'has_course_fav':has_course_fav,
'all_lessons': all_lessons,
'lesson_mun': lesson_num,
'cur_course_org': cur_course_org,
'reco_courses': reco_courses,
})

但是如果没有设置login_url的参数,需要确保settings.LOGIN_URL与你的登录视图正确关联。例如,使用默认值,可以添加下面几行到你的URLconf中:

1
2
3
from django.contrib.auth import views as auth_views
url(r'^users/login/$', auth_views.login),

settings.LOGIN_URL同时还接收视图函数名和命名的URL模式。这允许你自由地重新映射你的URLconf中的登录视图而不用更新设置。

还要注意一点就是login_required对于用户是否已经激活是不检查的。