Django的login_required装饰器与ajax搭配的小技巧

login_required是什么?

login_required是django提供的装饰器之一,主要用于检验用户进入该页面前,是否已经登录,如果用户没有认证,重定向到setting.py中LOGIN_URL字段值的路由。采用?next=连接登录后跳转的页面。重定向登录页面,登录后,将会跳转到?next=后面所接的路由。

1
2
3
4
5
6
7
8
9
10
11
12
13

# 使用装饰器

@login_required
def test(request):
pass

# 不使用装饰器

def test2(request):
if not request.user.is_authenticated:
return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))

注:

如果想自定义重定向的路径,可以这样写装饰器,@login_required(login_url='/consumer/login/')

这样就会重定向到/consumer/login了。


重点来了:上面所说的login_required登录之后跳转到原界面只是适用于form等其他页面跳转的情况,不适用于ajax异步请求

原因:ajax请求不会自动跳转页面,login_required需针对可跳转的页面才能够返回之前的页。所以我们需要手动调用window.location.href进行跳转。因此我需要获取?next后面的资源地址,然后传给前端(或者前端解析),成功登录后location.href重定向。

部分代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 后端

def get_previous_page(self,path):
"""get previous page which User just visited"""
if path == '':
return '/' # root directory
path_list = path.split('?next=')
common_logger.info(path_list[-1])
return path_list[-1]

def post(self, request):
"""消费者登录"""
login_id = request.data.get('login_id')
password = request.data.get('password')
path = request.data.get('next')
previous_page = self.get_previous_page(path)
try:
consumer = email_or_username_auth.authenticate(request, login_id, password)
if consumer:
login(request, consumer,backend='e_mall.authentication_consumer.Email_or_Username')
result = response_code.login_success
result.update({'previous_page':previous_page})
return Response(result)
return Response(response_code.login_error)
except Exception as e:
consumer_logger.error('login_error:{}'.format(str(e)))
return Response(response_code.server_error)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//前端
let data = {'login_id':username,'password':password,'next':next};
let headers = {'token':csrftoken};
let url = '/consumer/login-chsc-api/';
layer.load(0, {time: 1*10000});
$.ajax({
url:url,
type:'POST',
data:data,
headers:headers,
success:function(data){
if(data.code == 11){
layer.msg('登录成功,正在跳转...',{icon:1,time:500,closeBtn:0});
setTimeout(function(){ //延迟500ms执行
layer.closeAll('msg');
alert(data.previous_page);
location.href = data.previous_page; //父页采用parent,当前页采用window,最外层页采用top,实现重定向
},500);
}
else if(data.code == -10){
layer.msg('登录名或登录密码不正确!',{icon:2,time:1200,closeBtn:0});
}
else if(data.code == 500){
layer.msg('服务器无响应',{icon:2,time:1200,closeBtn:0});
}
layer.closeAll('loading');
},
error:function(){
layer.msg('服务器无响应!',{icon:2,time:1200,closeBtn:0});
layer.closeAll('loading');
},
});