当我们开发某个网站的时候,肯定会有用户登录和注册的功能,我们写好网页的时候,要是没有认证,知道路由就能访问资源(或者不想没有登录就让用户使用某个功能),用户登录的信息都是在cook里面,需要认证就去cook里面取值判断是否有该用户,当用户没有登录就去访问资源路由时,就拒绝访问,并自动跳转到登录页面...
最近在学flask,python里面有个强大的利器,生成器yield和装饰器@函数名,flask也用装饰器作路由,直接进入正题...
装饰器实际上就是一个函数,有两个特别之处:
先说下装饰器,举个栗子:
现在有某个需求:1.在打印run之前,要先打印一个Hello world 2.在所有函数执行之前,都要打印一个hello world。
我们可以向下面这种在每个函数里面加入print("hello world"),加入有几千个函数,一个个的加print("hello world"),不太现实!,如果某天又要打印其他的东西,又要一个一个修改,心态会爆炸的...
所以就不得不说装饰器的强大,能够一次给所有函数增加功能.
定一个函数:my_log,装饰器参数是一个函数,就随便写个形参。
def my_log(func):
在定义一个函数在my_log里面,作为返回值的函数,def wrapper(), 返回一个函数体。
def my_log(func):
def wrapper():
print("hello world")
func()
return wrapper
@my_log # 把my_log函数作为装饰器
def run():
print("run")
#执行run函数
run()
在解释一下上面的意思:等效于 run=my_log(run),1.装饰器器会先把run函数参进去my_log(run),2.然后返回的结果给run函数。run=my_log(run)。然后执行my_log函数,就先执行print("hello world"),然后执行 func()函数,func就是传进去的run函数,就会答应run。也就实现了所有函数之前打印hello world。
以后只要有函数要实现这个功能,我们就在函数名上一行加装饰器函数,@my_log,就ok了。
大概了解装饰器后然后进入真正的主题:用户登录认证(登录限制):
定义一个登录的装饰器函数:def login_requir()
保留一个源信息,用到wraps,把原函数名保留下来,使用之前的导入库:
from functools import wraps
def login_requir(func):
@wraps(func)#保留源信息,本质是endpoint装饰,否则修改函数名很危险
def inner(*args,**kwargs):#接收参数,*args接收多余参数形成元组,**kwargs接收对于参数形成字典
user=session.get('user_id') #表单接手网页中登录信息,存入到session中,判断用户是否登录
if not user:
return redirect('/login') #没有登录就跳转到登录路由下
return func(*args,**kwargs)#登录成功就执行传过来的函数
return inner
在每个需要判断用户登录之前都加入装饰器@login_requir,就能限制登录了...
再说下更好理解的装饰器:
@app.before_request#执行所有装饰器都要执行当前装饰器(简洁版实现同样功能)
def login_required():
if request.path in ['/login','/register']: #如果登录的路由是注册和登录就返会none
return None
user=session.get('user_id') #获取用户登录信息
if not user: #没有登录就自动跳转到登录页面去
return redirect('/login')
return None
上面的代码同样实现用户认证功能(登录限制),因为flask里面每个路由都是装饰器@app.route('/路由名')形成的路由,一个网站有很多路由,登录路由,注册路由,首页展示路由....当用户使用其他路由的时而没有登录的时候,我们就自动跳转到登录页面去。