在阐述什么是装饰器前,我们先来说一下什么是闭包
闭包:
在一个外函数中 定义了一个内函数
内函数运用了 外函数的临时变量
外函数的返回值 是内函数的引用
def outer():
a=100
def inner():
b=a+100
print(b)
return inner
outer()()
装饰器:
以 @开头,装饰器是在函数调用之上的修饰器,在不改变项目原有代码的基础上,增加一些额外的功能
装饰器使用场景
授权:装饰器能有助于检查某个人是否被授权去使用一个 web 应用的端点 (endpoint)。它们被大量使用于 Flask 和 Django web 框架中
日志:在记录日志的地方添加装饰器
缓存:通过装饰器获取缓存中的值
函数装饰器
一个装饰器:
def outer(func):
def inner(a,b) / def inner(*args,**kwargs):
print(“ 特殊效验功能的执行 ”)
func(a,b) / func(*args,**kwargs)
print(“ 停止执行 ”)
return inner
@outer
def f(a,b):
print(“a+b=”,(a+b))
f(10,20)
# 输出结果:
特殊效验功能的执行
30
停止执行
多个装饰器:
开始:自上而下
结束:自下而上
def outer1(func):
def inner(a,b) / def inner(*args,**kwargs):
print(“ 特殊效验功能 1 的执行 ”)
print(“111111111111”)
func(a,b) / func(*args,**kwargs)
print(“1 停止执行 ”)
print(“111111111111”)
return inner
def outer2(func):
def inner(a,b) / def inner(*args,**kwargs):
print(“ 特殊效验功能 2 的执行 ”)
print(“222222222222”)
func(a,b) / func(*args,**kwargs)
print(“2 停止执行 ”)
print(“222222222222”)
return inner
@outer1
@outer2
def f(a,b):
print(“a+b=”,(a+b))
f(10,20)
输出结果:特殊功能效验 1 的执行
111111111111
特殊功能效验 2 的执行
222222222222
30
2 停止执行
222222222222
1 停止执行
111111111111
类装饰器的运用
这里的代码,展示的是 jwt 和 类装饰的结合使用
目的:防止用户 使用他人敏感信息 进行篡改
import jwt
装饰器
def my_decorator(func):
def wrapper(request,*args,**kwargs):
print(‘ 这个装饰器被调用了 ’)
print(‘ 请求接口地址是 %s’ % request.path)
判断 jwt 逻辑
uid = request.GET.get(“uid”)
clinet_jwt = request.GET.get(“jwt”,None)
if clinet_jwt is None:
return HttpResponse(‘ 没有令牌 ’)
decode_jwt = jwt.decode(clinet_jwt,’123′,algorithms=[‘HS256’])
if decode_jwt[‘uid’] != str(uid):
return HttpResponse(‘ 你篡改了用户 id’)
return func(request,*args,**kwargs)
return wrapper
类装饰器调用
from django.utils.decorators import method_decorator
在查询用户信息类时 调用
用户信息
class UserInfo(APIView):
@method_decorator(my_decorator)
def get(self,request):
uid = request.GET.get(‘uid’)
查询数据
user = User.objects.get(id=int(uid))
序列化对象
user_ser = UserSer(user)
return Response(user_ser.data)
在 用户登录接口 后端
登录接口
class Login(APIView):
def get(self,request):
接收参数
username = request.GET.get(‘username’,’ 没有接受到 ’)
password = request.GET.get(‘password’,’ 没有接受到 ’)
查询数据
user = User.objects.filter(username=username,password=make_password(password)).first()
if user:
res = {}
res[‘code’] = 200
res[‘message’] = ‘ 登录成功 ’
res[‘username’] = user.username
res[‘uid’] = user.id
加入 jwt 编码机制
进行编码
智汇代理申请 http://www.kaifx.cn/broker/th…
encode_jwt = jwt.encode({‘uid’:str(user.id)},’123′,algorithm=’HS256′)
解码操作
强转
encode_str = encode_jwt.decode(‘utf-8’)
res[‘jwt’] = encode_str
return Response(res)
else:
res = {}
res[‘code’] = 405
res[‘message’] = ‘ 用户名或密码错误 ’
return Response(res)
在前端的登录 接口中 要将 jwt 存储到 localStorage 里面
localStorage.setItem(‘jwt’,result.data.jwt)