Flask 添加登陆验证装饰器报错,及解析

写这个之前,是想到一个需求,这个是关于之前写Flask笔记(二)中的一个知识点,路由相关

需求为 : 有一些页面必须是登陆之后才能访问的,比如ShoppingCart,说白了就是写一个登陆验证,那怎么才能知道当前这个请求 就是登陆状态的呢?如果不是登陆状态,那应该重定向到login页面

  1. from flask import Flask,request,session,redirect,url_for
  2. app = Flask(__name__)
  3. # 如果要使用session,必须为SECRET_KEY设置一个值,原因我之后会在session和cookie那里讲
  4. app.config['SECRET_KEY'] = 'zhuchunyudashuaibi'
  5. def auth_login(function):
  6. """登陆验证装饰器,如果是登陆状态的话,is_login为真"""
  7. def inner(*args,**kwargs):
  8. is_login = session.get("is_login",None)
  9. if is_login:
  10. return function(*args,**kwargs)
  11. else:
  12. url = url_for("login")
  13. return redirect(url)
  14. return inner
  15. @app.route('/shopcart',methods = ["GET","POST"])
  16. @auth_login
  17. def shopCart():
  18. '''购物车页面'''
  19. return "shopCart pages"
  20. @app.route("/login",methods=["GET","POST"])
  21. def login():
  22. if request.method == "POST":
  23. name = request.form.get("name")
  24. password = request.form.get("password")
  25. if name == "朱宇" and password == "123":
  26. session["name"] = name
  27. session["password"] = password
  28. session["is_login"] = True
  29. return " login sucess !! "
  30. else:
  31. return " login faild "
  32. return 'login.html'
  33. if __name__ == "__main__":
  34. app.run()

启动测试一下,下面是截图,表示设置成功了

但是我再基于上面的代码,再加一个视图函数,pay 视图函数吧。下面是代码

  1. @app.route('/pay',methods = ["GET","POST"])
  2. @auth_login
  3. def pay():
  4. '''支付页面'''
  5. return "pay pages"

再次启动一下,你会发现这时候就报错了

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

先看我写的一段测试代码

看到它的打印效果了嘛,这样就可以说明问题

  1. 先是decorator_a这个函数,将f作为参数传递,得到这样的结果 inner_a = decorator_a(f)
  2. 再将inner_a最为参数传递给 decorator_b 最后得到inner_b
  1. # 我们现在来仔细的研究下这段代码
  2. @app.route('/pay',methods = ["GET","POST"])
  3. @auth_login
  4. def pay():
  5. '''支付页面'''
  6. return "pay pages"
  1. pay 函数作为参数传递给auth_login ,便会执行auth_login 函数,得到返回值 inner 函数,上面代码可以改成下面这个样子

    1. @app.route('/pay',methods = ["GET","POST"])
    2. inner函数的内存地址
  2. @app.route('/pay',methods = ["GET","POST"]) ,route它是直接加了括号的,所以应该是@decorator, 那么会将 inner 传递给函数 decorator ,便会执行 decorator

    1. def decorator(f):
    2. endpoint = options.pop('endpoint', None)
    3. self.add_url_rule(rule, endpoint, f, **options)
    4. 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这部分。

    1. def add_url_rule(self, rule, endpoint=None, view_func=None,provide_automatic_options=None, **options):
    2. if endpoint is None:
    3. endpoint = _endpoint_from_view_func(view_func)
    4. options['endpoint'] = endpoint

    判断endpoint 为None的话,便会将 _endpoint_from_view_func(view_func) 的返回值赋值给 endpoint ,最后以key为endpoint(这里是一个字典的key值,一个字符串) , 将变量 endpoint 为values值,view_func 这个变量就是inner 函数,继续看 _endpoint_from_view_func 方法

    1. def _endpoint_from_view_func(view_func):
    2. """Internal helper that returns the default endpoint for a given
    3. function. This always is the function name.
    4. """
    5. assert view_func is not None, 'expected view func if endpoint ' \
    6. 'is not provided.'
    7. return view_func.__name__

    最终返回了函数的__name__的值,所以 endpoint=inner(这个inner是一个字符串了) 最终它是以endpoint的值来进行url和视图函数之间的对应关系的,怎么证明?很简单,我们回到最初时候的代码,flask程序没有报错之前,在app.run() 前一行加这样一段代码 print(app.url_map()) 它的作用就是打印出url映射关系。

    我只为shopCart 加了登陆验证装饰器,它所对应的视图函数为inner ,再看其他的Ruleapp.route 我都没有设置endpoint 的值,所以都是对应想应的视图函数的__name__

好了,解释了一大推报错的原因,那么我们怎么改,才不会有BUG呢?我们为pay 函数加了登陆验证的装饰器,这跟为shopCart加不是一样么,出现了两个inner 的对应关系,所以报错了。我们只需为这个两个视图函数添加不同的endpoint 值就好了,最好是有标识性的,反向解析可能也用得上。下面是改进的代码

  1. from flask import Flask,request,session,redirect,url_for
  2. app = Flask(__name__)
  3. # 如果要使用session,必须为SECRET_KEY设置一个值,原因我之后会在session和cookie那里讲
  4. app.config['SECRET_KEY'] = 'zhuchunyudashuaibi'
  5. def auth_login(function):
  6. """登陆验证装饰器,如果是登陆状态的话,is_login为真"""
  7. def inner(*args,**kwargs):
  8. is_login = session.get("is_login",None)
  9. if is_login:
  10. return function(*args,**kwargs)
  11. else:
  12. url = url_for("login")
  13. return redirect(url)
  14. return inner
  15. @app.route('/shopCart', methods=["GET", "POST"],endpoint='shopCart')
  16. @auth_login
  17. def shopCart():
  18. '''购物车页面'''
  19. return "shopCart pages"
  20. @app.route('/pay', methods=["GET", "POST"],endpoint='pay')
  21. @auth_login
  22. def pay():
  23. '''支付页面'''
  24. return "pay pages"
  25. @app.route("/login",methods=["GET","POST"])
  26. def login():
  27. if request.method == "POST":
  28. name = request.form.get("name")
  29. password = request.form.get("password")
  30. if name == "朱宇" and password == "123":
  31. session["name"] = name
  32. session["password"] = password
  33. session["is_login"] = True
  34. return " login sucess !! "
  35. else:
  36. return " login faild "
  37. return 'login.html'
  38. if __name__ == "__main__":
  39. app.run()

好了,这个知识点就总结完了,希望看到的同学,对你有所帮助吧!

flask笔记(三)Flask 添加登陆验证装饰器报错,及解析的更多相关文章

  1. Django之Cookie Session详解,CBV,FBV登陆验证装饰器和自定义分页

    Cookie Session和自定义分页   cookie Cookie的由来 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接 ...

  2. create-react-app @observer装饰器报错

    npm install --save-dev babel-plugin-transform-decorators-legacy 然后在node_modules/babel-preset-react-a ...

  3. mongodb添加登陆验证

    mongodb添加登陆验证 转载地址 清空log,db目录 mongod --auth --logpath "D:\mongodb\log\log.log" --logappend ...

  4. Python学习笔记之生成器、迭代器和装饰器

    这篇文章主要介绍 Python 中几个常用的高级特性,用好这几个特性可以让自己的代码更加 Pythonnic 哦 1.生成器 什么是生成器呢?简单来说,在 Python 中一边循环一边计算的机制称为 ...

  5. 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 ...

  6. CORDOVA :添加cordova-plugin-file-opener2插件cordova打包报错

    原文:CORDOVA :添加cordova-plugin-file-opener2插件cordova打包报错 最近在接触android项目,其中涉及到APP自动更新的问题,当新APP下载成功后需要打开 ...

  7. Flask(2):登陆验证

    装饰器补充: import functools def auth(func): @functools.wraps(func) # 作用:把原函数的原信息封装到 inner 中 def inner(*a ...

  8. python全栈开发day111-flask路由及其参数,Flask配置,蓝图,几个装饰器、闪现、send_file、jsonify

    1.endpoint参数,解决视图函数重名问题(包括装饰后重名问题) http://www.cnblogs.com/eric-nirnava/p/endpoint.html 每个应用程序app都有一个 ...

  9. 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 ...

随机推荐

  1. windows下快速修改host文件

    windows下快速修改host文件 win+r  输入 notepad c:\Windows\System32\drivers\etc\hosts

  2. [LeetCode]23. Merge k Sorted Lists合并K个排序链表

    Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity. E ...

  3. python unix时间戳

    这是第一次用着python感到怒了,从datetime转化到timestamp数值居然没有直接的函数 直接获取当前时间戳倒是方便: import time timestamp = time.time( ...

  4. BZOJ4010: [HNOI2015]菜肴制作(拓扑排序 贪心)

    题意 题目链接 Sol 震惊,HNOI竟出NOI原题 直接在反图上贪心一下. // luogu-judger-enable-o2 // luogu-judger-enable-o2 #include& ...

  5. eclipse的应用和整理

    1如何在eclipse中获取动态项目的绝对路径 1.鼠标选中项目,右击菜单,选择properties2.出来弹出框,选择resource,location的值就是你想要的项目绝对路径 JSP中获得当前 ...

  6. JSP初学者2

    <jsp:useBean id="name" class="classname" scope="page|request|session|app ...

  7. Unity Android 真机调试

    官方文档 https://docs.unity3d.com/Manual/AttachingMonoDevelopDebuggerToAnAndroidDevice.html 然而 按照官方文档 很多 ...

  8. matlab练习程序(Arnold图像置乱)

    自从上次写了Hilbert图像置乱之后,就对图像置乱研究了一下,发现这里面也是有很多置乱算法的. Arnold也算一种比较主要的置乱算法,算法由以下变换公式产生: 这里a和b是参数,n是迭代次数,N是 ...

  9. Python单元测试框架unittest使用方法讲解

    这篇文章主要介绍了Python单元测试框架unittest使用方法讲解,本文讲解了unittest概述.命令行接口.测试案例自动搜索.创建测试代码.构建测试套件方法等内容,需要的朋友可以参考下   概 ...

  10. pdf2swf 转换时报错。This file is too complex to render- SWF only supports 65536 shapes at once

    在使用swftools转换pdf 到swf的时候报错,有如下说明:if the pdf contains too many images / shapes, pdf2swf will fail wit ...