decrators.py
3.95 KB
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# coding: utf-8
import django.http
from functools import wraps
from django.conf import settings
from django.utils.decorators import available_attrs
from django.shortcuts import resolve_url
from django.utils.six.moves.urllib.parse import urlparse
def weapp_django_logout(request, response):
assert isinstance(request, django.http.HttpRequest)
assert isinstance(response, django.http.HttpResponse)
# 请求统一认证登出
response.delete_cookie('pt')
response.delete_cookie('pu')
response.delete_cookie('username')
return response
def weapp_logout(func=weapp_django_logout):
"""
Django登出视图函数装饰器
:param func: 处理登出逻辑的函数,接受request和response两个参数
:return:
"""
return auth_decorator_factory(func)
def auth_decorator_factory(func=None):
"""
登录登出装饰器工厂函数,允许用户自定义外部登录登出函数
:param func:
:return:
"""
def decorator(view_func):
@wraps(view_func)
def _wrapped_view(request, *args, **kwargs):
response = view_func(request, *args, **kwargs)
if func:
func(request, response)
return response
return _wrapped_view
return decorator
import json
from django.http import JsonResponse
class QCCRJsonResponse(JsonResponse):
"""
封装了返回码和信息的JsonResponse类
"""
def __init__(self, obj=None, code=200, msg="success", status=200, **kwargs):
data = {"code": code, "msg": msg, "result": json.loads(obj) if isinstance(obj, (str, unicode)) else obj}
super(QCCRJsonResponse, self).__init__(data=data, status=status, **kwargs)
class QCCRErrorResponse(QCCRJsonResponse):
"""
请求错误
"""
def __init__(self, obj=None, code=400, msg="failure", status=400, **kwargs):
super(QCCRErrorResponse, self).__init__(obj=obj, code=code, msg=msg, status=status, **kwargs)
def user_passes_test(test_func, login_url=None,
redirect_field_name=getattr(settings, "QCCR_REDIRECT_FIELD_NAME", 'redirect')):
"""
本装饰器通过test_func函数,检查views是否通过相应的检测,未通过则跳转到登录页面;test_func函数接受user对象作为参数,通过则返回True
"""
def decorator(view_func):
@wraps(view_func, assigned=available_attrs(view_func))
def _wrapped_view(request, *args, **kwargs):
if test_func(request.user):
return view_func(request, *args, **kwargs)
# 如果未通过检查,且为ajax请求,返回403
if request.is_ajax():
return QCCRErrorResponse(code=403, msg="用户身份检查失败", status=403)
# 非ajax请求,跳转到登录页面
path = request.build_absolute_uri()
resolved_login_url = resolve_url(login_url or getattr(settings, "QCCR_LOGIN_URL", '/login/'))
login_scheme, login_netloc = urlparse(resolved_login_url)[:2]
current_scheme, current_netloc = urlparse(path)[:2]
if ((not login_scheme or login_scheme == current_scheme) and
(not login_netloc or login_netloc == current_netloc)):
path = request.get_full_path()
from django.contrib.auth.views import redirect_to_login
return redirect_to_login(path, resolved_login_url, redirect_field_name)
return _wrapped_view
return decorator
def weapp_login_required(function=None,
redirect_field_name=getattr(settings, "QCCR_REDIRECT_FIELD_NAME", 'redirect'),
login_url=None):
"""
登录状态检查装饰器,如果未登录,则直接跳转到登录页面
"""
actual_decorator = user_passes_test(
lambda u: u.is_authenticated(),
login_url=login_url,
redirect_field_name=redirect_field_name
)
if function:
return actual_decorator(function)
return actual_decorator