flask笔记(三)Flask 添加登陆验证装饰器报错,及解析
Flask 添加登陆验证装饰器报错,及解析
写这个之前,是想到一个需求,这个是关于之前写Flask笔记(二)中的一个知识点,路由相关
需求为 : 有一些页面必须是登陆之后才能访问的,比如ShoppingCart,说白了就是写一个登陆验证,那怎么才能知道当前这个请求 就是登陆状态的呢?如果不是登陆状态,那应该重定向到login页面
from flask import Flask,request,session,redirect,url_for
app = Flask(__name__)
# 如果要使用session,必须为SECRET_KEY设置一个值,原因我之后会在session和cookie那里讲
app.config['SECRET_KEY'] = 'zhuchunyudashuaibi'
def auth_login(function):
"""登陆验证装饰器,如果是登陆状态的话,is_login为真"""
def inner(*args,**kwargs):
is_login = session.get("is_login",None)
if is_login:
return function(*args,**kwargs)
else:
url = url_for("login")
return redirect(url)
return inner
@app.route('/shopcart',methods = ["GET","POST"])
@auth_login
def shopCart():
'''购物车页面'''
return "shopCart pages"
@app.route("/login",methods=["GET","POST"])
def login():
if request.method == "POST":
name = request.form.get("name")
password = request.form.get("password")
if name == "朱宇" and password == "123":
session["name"] = name
session["password"] = password
session["is_login"] = True
return " login sucess !! "
else:
return " login faild "
return 'login.html'
if __name__ == "__main__":
app.run()
启动测试一下,下面是截图,表示设置成功了

但是我再基于上面的代码,再加一个视图函数,pay 视图函数吧。下面是代码
@app.route('/pay',methods = ["GET","POST"])
@auth_login
def pay():
'''支付页面'''
return "pay pages"
再次启动一下,你会发现这时候就报错了

报错的原因是:inner这个函数重复了,我们在哪里写了inner 函数?对,没错就是登陆验证装饰器
先看我写的一段测试代码

看到它的打印效果了嘛,这样就可以说明问题
- 先是
decorator_a这个函数,将f作为参数传递,得到这样的结果inner_a=decorator_a(f) - 再将
inner_a最为参数传递给decorator_b最后得到inner_b
# 我们现在来仔细的研究下这段代码
@app.route('/pay',methods = ["GET","POST"])
@auth_login
def pay():
'''支付页面'''
return "pay pages"
pay函数作为参数传递给auth_login,便会执行auth_login函数,得到返回值inner函数,上面代码可以改成下面这个样子@app.route('/pay',methods = ["GET","POST"])
inner函数的内存地址
@app.route('/pay',methods = ["GET","POST"]),route它是直接加了括号的,所以应该是@decorator, 那么会将inner传递给函数decorator,便会执行decorator。def decorator(f):
endpoint = options.pop('endpoint', None)
self.add_url_rule(rule, endpoint, f, **options)
return f
这里的参数
f就是 函数inner既然写到这里了,那就继续看
self.add_url_rule(rule, endpoint, f, **options),我先说这个参数现在是什么值 ,rule='/pay',endpoint=None因为app.route方法没有传递该参数,所以为None,f=inner,记住参数的值,我们看
add_url_rule的部分源码,只看endpoint这部分。def add_url_rule(self, rule, endpoint=None, view_func=None,provide_automatic_options=None, **options):
if endpoint is None:
endpoint = _endpoint_from_view_func(view_func)
options['endpoint'] = endpoint
判断
endpoint为None的话,便会将_endpoint_from_view_func(view_func)的返回值赋值给endpoint,最后以key为endpoint(这里是一个字典的key值,一个字符串), 将变量endpoint为values值,view_func这个变量就是inner函数,继续看_endpoint_from_view_func方法def _endpoint_from_view_func(view_func):
"""Internal helper that returns the default endpoint for a given
function. This always is the function name.
"""
assert view_func is not None, 'expected view func if endpoint ' \
'is not provided.'
return view_func.__name__
最终返回了函数的
__name__的值,所以endpoint=inner(这个inner是一个字符串了)最终它是以endpoint的值来进行url和视图函数之间的对应关系的,怎么证明?很简单,我们回到最初时候的代码,flask程序没有报错之前,在app.run()前一行加这样一段代码print(app.url_map())它的作用就是打印出url映射关系。
我只为
shopCart加了登陆验证装饰器,它所对应的视图函数为inner,再看其他的Rule,app.route我都没有设置endpoint的值,所以都是对应想应的视图函数的__name__。
好了,解释了一大推报错的原因,那么我们怎么改,才不会有BUG呢?我们为pay 函数加了登陆验证的装饰器,这跟为shopCart加不是一样么,出现了两个inner 的对应关系,所以报错了。我们只需为这个两个视图函数添加不同的endpoint 值就好了,最好是有标识性的,反向解析可能也用得上。下面是改进的代码
from flask import Flask,request,session,redirect,url_for
app = Flask(__name__)
# 如果要使用session,必须为SECRET_KEY设置一个值,原因我之后会在session和cookie那里讲
app.config['SECRET_KEY'] = 'zhuchunyudashuaibi'
def auth_login(function):
"""登陆验证装饰器,如果是登陆状态的话,is_login为真"""
def inner(*args,**kwargs):
is_login = session.get("is_login",None)
if is_login:
return function(*args,**kwargs)
else:
url = url_for("login")
return redirect(url)
return inner
@app.route('/shopCart', methods=["GET", "POST"],endpoint='shopCart')
@auth_login
def shopCart():
'''购物车页面'''
return "shopCart pages"
@app.route('/pay', methods=["GET", "POST"],endpoint='pay')
@auth_login
def pay():
'''支付页面'''
return "pay pages"
@app.route("/login",methods=["GET","POST"])
def login():
if request.method == "POST":
name = request.form.get("name")
password = request.form.get("password")
if name == "朱宇" and password == "123":
session["name"] = name
session["password"] = password
session["is_login"] = True
return " login sucess !! "
else:
return " login faild "
return 'login.html'
if __name__ == "__main__":
app.run()
好了,这个知识点就总结完了,希望看到的同学,对你有所帮助吧!
flask笔记(三)Flask 添加登陆验证装饰器报错,及解析的更多相关文章
- Django之Cookie Session详解,CBV,FBV登陆验证装饰器和自定义分页
Cookie Session和自定义分页 cookie Cookie的由来 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接 ...
- create-react-app @observer装饰器报错
npm install --save-dev babel-plugin-transform-decorators-legacy 然后在node_modules/babel-preset-react-a ...
- mongodb添加登陆验证
mongodb添加登陆验证 转载地址 清空log,db目录 mongod --auth --logpath "D:\mongodb\log\log.log" --logappend ...
- Python学习笔记之生成器、迭代器和装饰器
这篇文章主要介绍 Python 中几个常用的高级特性,用好这几个特性可以让自己的代码更加 Pythonnic 哦 1.生成器 什么是生成器呢?简单来说,在 Python 中一边循环一边计算的机制称为 ...
- Linux下登陆MySQL时遇到报错"RROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) "
前言 作者在2021-07-21时遇到 linux下登陆MySQL时遇到报错"RROR 1045 (28000): Access denied for user 'root'@'localh ...
- CORDOVA :添加cordova-plugin-file-opener2插件cordova打包报错
原文:CORDOVA :添加cordova-plugin-file-opener2插件cordova打包报错 最近在接触android项目,其中涉及到APP自动更新的问题,当新APP下载成功后需要打开 ...
- Flask(2):登陆验证
装饰器补充: import functools def auth(func): @functools.wraps(func) # 作用:把原函数的原信息封装到 inner 中 def inner(*a ...
- python全栈开发day111-flask路由及其参数,Flask配置,蓝图,几个装饰器、闪现、send_file、jsonify
1.endpoint参数,解决视图函数重名问题(包括装饰后重名问题) http://www.cnblogs.com/eric-nirnava/p/endpoint.html 每个应用程序app都有一个 ...
- Flask框架实现给视图函数增加装饰器操作示例
在@app.route的情况下增加装饰器的写法: ? 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 2 ...
随机推荐
- ASP.NET内置对象-网页转向的4中方法
ASP.NET页面跳转的方法 1.超链接 2.Response.Redirect(“Urlstring”) 3.Server.Transfer(“UrlString”) 4.PostBackUrl 1 ...
- 关于GBK、GB2312、UTF8之间的区别
UTF-8:Unicode Transformation Format-8bit,允许含BOM,但通常不含BOM.是用以解决国际上字符的一种多字节编码,它对英文使用8位(即一个字节),中文使用24为( ...
- Javaweb三大组件-过滤器、监听器
1. 过滤器 [filter] 作用: 对单个获取多个servlet起到增强[advice]的作用. 用于在所有的servlet执行前,做一些预处理.例如:做编码处理, 访问量统计[servletCo ...
- mysql三-3:完整性约束
一.完整性约束介绍 约束条件与数据类型的宽度一样,都是可选参数 作用:用于保证数据的完整性和一致性主要分为: PRIMARY KEY (PK) 标识该字段为该表的主键,可以唯一的标识记录 FOREIG ...
- SQLAlchemy的使用---查询的更多操作
# 查询更多操作 from create_table import User, engine from sqlalchemy.orm import sessionmaker Session = ses ...
- 洛谷P1730 最小密度路径(floyd)
题意 题目链接 Sol zz floyd. 很显然的一个dp方程\(f[i][j][k][l]\)表示从\(i\)到\(j\)经过了\(k\)条边的最小权值 可以证明最优路径的长度一定\(\leqsl ...
- Python爬虫实战:将网页转换为pdf电子书
写爬虫似乎没有比用 Python 更合适了,Python 社区提供的爬虫工具多得让你眼花缭乱,各种拿来就可以直接用的 library 分分钟就可以写出一个爬虫出来,今天就琢磨着写一个爬虫,将廖雪峰的 ...
- sql注入一点小心得
好久没写技术博客,最近研究产品关于用户体验方面较多,加上项目突然比较多,设计原型.跟进开发.设计师等工作着实没时间写博客. 接下来技术上主要php深入学习和mysql优化.这两天看了关于sql注入方面 ...
- SharePoint Config database Log file too big – reduce it!
SharePoint Config database logs are one thing to keep an eye on since they do have a tendency to gro ...
- 如何将使用托管磁盘虚拟机的 OS 盘挂载到其他虚拟机上
适用场景 当出现虚拟机无法启动等情况时,需要将虚拟机的 OS 磁盘挂载到其他虚拟机上进行问题诊断或者数据恢复.使用托管磁盘的虚拟机无法通过存储浏览器等工具进行管理,只能通过 PowerShell 来操 ...