Flask的路由、蓝图和装饰器
复习装饰器
基于session编写登录验证的装饰器。
- 思考:如何给两个以上的视图函数增加装饰器
def is_login(func):def inner(*args, **kwargs):if session.get('username'):ret = func(*args, **kwargs)else:return redirect('/login')return retreturn inner
测试给两个以上的视图函数增加装饰器出现的报错信息
"AssertionError: View function mapping is overwriting an existing endpoint function: inner"# 百度翻译 # 主动抛出异常, 视图函数存在重名 "断言错误:视图函数映射覆盖现有终结点函数:内部"
解决方法1:
把 inner 改掉,保留原始的函数名字,这样返回的不是相同的 inner 了。 --- functools.wraps(func)
from functools import wrapsdef is_login(func):@wraps(func)def inner(*args, **kwargs):if session.get('username'):ret = func(*args, **kwargs)else:return redirect('/login')return retreturn inner
解决方法2:
加入endpoint,在对应mapping映射的时候,不会出现视图函数重名。 --- endpoint: 路由关系映射, 别名
def is_login(func):def inner(*args, **kwargs):if session.get('username'):ret = func(*args, **kwargs)else:return redirect('/login')return retreturn inner@app.route('/home', endpoint="home") @is_login def home():return render_template('home.html', sd=STUDENT_DICT)@app.route('/student', endpoint="student") @is_login def student():id = request.args.get('id')student = STUDENT_DICT.get(int(id), None)return render_template('student.html', student=student, id=id)if __name__ == '__main__':app.run('0.0.0.0', 9999)
Flask中的路由
endpoint (映射路由-视图函数)
是用来映射的,可以路由映射视图函数,当然也可以视图函数映射路由。
视图函数__name__ = " " 可通过url_for("endpoint的值")方法获取到请求路径(反向解析)
# 测试,导入url_for from flask import (Flask, request, render_template, redirect, session, url_for)@app.route('/login', methods=['POST', 'GET'], endpoint='loginxxx') def login():print(url_for("loginxxx"))if request.method == "GET":return render_template('login.html')else:username = request.form.get('username')password = request.form.get('pwd')if username == '123' and password == "123":session["username"] = usernamereturn render_template('home.html', sd=STUDENT_DICT)else:return redirect('/login')# 运行结果:/login
methods
可迭代对象,元组、列表都可以
例如:
methods = ["get","Post"] # 当前视图函数支持的请求方法 # 源码中会有upper,所以大小写无所谓。
如果请求方法不在methods里面会抛出HTTP的状态码:405 请求方式不被允许
defaults(默认参数,不常用)
@app.route('/login', methods=['POST', 'GET'], endpoint='loginxxx', defaults={'id':5}) def login(id):print(url_for("loginxxx"),id)if request.method == "GET":return render_template('login.html')else:username = request.form.get('username')password = request.form.get('pwd')if username == '123' and password == "123":session["username"] = usernamereturn render_template('home.html', sd=STUDENT_DICT)else:return redirect('/login')# 结果: /login 5
注意事项:
一旦默认参数存在,视图函数中必须有一个形参去接收,形参变量名必须与 defaults 中定义的一致。
strict_slashes=True
是否严格遵循路由匹配规则 "/",默认是True
@app.route('/login', methods=['POST', 'GET'], endpoint='loginxxx',strict_slashes=False) def login():print(url_for("loginxxx"))if request.method == "GET":return render_template('login.html')else:username = request.form.get('username')password = request.form.get('pwd')if username == '123' and password == "123":session["username"] = usernamereturn render_template('home.html', sd=STUDENT_DICT)else:return redirect('/login')# 更改成False后,加上/也是可以访问的。
redirect_to
redirect_to = "/login" # 永久重定向 301 308 不经过视图函数的
动态参数路由(重点)
@app.route("/login/<int:page>") 指定int类型 /login/1
@app.route("/login/<floder>/<filename>") 默认是str类型 /login/templates/index.html
分页的场景:
@app.route('/home/<int:page>', endpoint="home") @is_login def home(page):print(page)return render_template('home.html', sd=STUDENT_DICT)
输入什么数字,便会在控制台打印出来,也可以多个(加多个<int:page1>/<int:page2>)等等,不过必须要是定长的。
不过是有问题的,如果输入0的时候不小心输入了o,那就会报错,解决方法,更改成string就行,默认就是string,string也是包含int的。
什么都不写,也是string的。
@app.route('/home/<page>', endpoint="home") @is_login def home(page):print(page)return render_template('home.html', sd=STUDENT_DICT)
另一种:
from flask import (Flask, request, render_template, redirect, session, url_for, send_file)@app.route('/home/<filename>', endpoint="home") @is_login def home(filename):return send_file(filename)
Flask中的配置
1.初始化配置
- app = Flask(__name__, template_folder="")
- template_folder="" 更改模板存放目录, 默认值templates
- static_folder="" 静态文件存放路径 - 默认是/static
- static_url_path="" 静态文件访问路径 - 默认是 "/"+static_folder
-- 静态文件存放路径: 存放静态文件的实际路径, 根据该路径寻找服务器中存放的相应静态文件
-- 静态文件访问路径: 相当于静态文件存放路径的别名, 只要请求该访问路径即相当于在静态文件的存放路径下查找资源
2.Config 对象配置
- app.config["DEBUG"] = True 和 app.debug = True 效果一样。
- app.default_config 查看所有配置
- DEBUG --- 编码阶段 代码重启 日志输出级别很低 页面中会显示错误 错误会展示代码暴露后台信息
- TESTING --- 测试阶段 日志输出级别较高 无限接近线上环境
- app.config[JSON_MIMETYPE] = 1231/21312
app.default_config 查看所有配置
config中有用的key
{'DEBUG': False, # 是否开启Debug模式'TESTING': False, # 是否开启测试模式'PROPAGATE_EXCEPTIONS': None, # 异常传播(是否在控制台打印LOG) 当Debug或者testing开启后,自动为True'PRESERVE_CONTEXT_ON_EXCEPTION': None, # 一两句话说不清楚,一般不用它'SECRET_KEY': None, # 之前遇到过,在启用Session的时候,一定要有它'PERMANENT_SESSION_LIFETIME': 31, # days , Session的生命周期(天)默认31天'USE_X_SENDFILE': False, # 是否弃用 x_sendfile'LOGGER_NAME': None, # 日志记录器的名称'LOGGER_HANDLER_POLICY': 'always','SERVER_NAME': None, # 服务访问域名'APPLICATION_ROOT': None, # 项目的完整路径'SESSION_COOKIE_NAME': 'session', # 在cookies中存放session加密字符串的名字'SESSION_COOKIE_DOMAIN': None, # 在哪个域名下会产生session记录在cookies中'SESSION_COOKIE_PATH': None, # cookies的路径'SESSION_COOKIE_HTTPONLY': True, # 控制 cookie 是否应被设置 httponly 的标志,'SESSION_COOKIE_SECURE': False, # 控制 cookie 是否应被设置安全标志'SESSION_REFRESH_EACH_REQUEST': True, # 这个标志控制永久会话如何刷新'MAX_CONTENT_LENGTH': None, # 如果设置为字节数, Flask 会拒绝内容长度大于此值的请求进入,并返回一个 413 状态码'SEND_FILE_MAX_AGE_DEFAULT': 12, # hours 默认缓存控制的最大期限'TRAP_BAD_REQUEST_ERRORS': False,# 如果这个值被设置为 True ,Flask不会执行 HTTP 异常的错误处理,而是像对待其它异常一样,# 通过异常栈让它冒泡地抛出。这对于需要找出 HTTP 异常源头的可怕调试情形是有用的。'TRAP_HTTP_EXCEPTIONS': False,# Werkzeug 处理请求中的特定数据的内部数据结构会抛出同样也是“错误的请求”异常的特殊的 key errors 。# 同样地,为了保持一致,许多操作可以显式地抛出 BadRequest 异常。# 因为在调试中,你希望准确地找出异常的原因,这个设置用于在这些情形下调试。# 如果这个值被设置为 True ,你只会得到常规的回溯。'EXPLAIN_TEMPLATE_LOADING': False,'PREFERRED_URL_SCHEME': 'http', # 生成URL的时候如果没有可用的 URL 模式话将使用这个值'JSON_AS_ASCII': True,# 默认情况下 Flask 使用 ascii 编码来序列化对象。如果这个值被设置为 False ,# Flask不会将其编码为 ASCII,并且按原样输出,返回它的 unicode 字符串。# 比如 jsonfiy 会自动地采用 utf-8 来编码它然后才进行传输。'JSON_SORT_KEYS': True,#默认情况下 Flask 按照 JSON 对象的键的顺序来序来序列化它。# 这样做是为了确保键的顺序不会受到字典的哈希种子的影响,从而返回的值每次都是一致的,不会造成无用的额外 HTTP 缓存。# 你可以通过修改这个配置的值来覆盖默认的操作。但这是不被推荐的做法因为这个默认的行为可能会给你在性能的代价上带来改善。'JSONIFY_PRETTYPRINT_REGULAR': True,'JSONIFY_MIMETYPE': 'application/json','TEMPLATES_AUTO_RELOAD': None, }
以上这些Key,都可以被改写,当然他们也都是有默认值存在的,如果没有特殊情况,不要改写它的默认值
修改配置的方式大约是两种
1.直接对app.config进行修改
app.config["DEBUG"] = True
2.setting文件快速配置DEBUG与TESTING
config的特性
app.config.from_object() 写入的类中定义了什么就添加什么 class Debugsetting(object):DEBUG = True
具体配置:
1.在项目路径下新建settings.py文件, 在文件中编写 class class DebugSettings(object):DEBUG = TrueSECRET_KEY = "123456"SESSION_COOKIE_NAME = "I am debug session" class TestingSettings(object):TESTING = TrueSECRET_KEY = "!@#$%^&*()_"SESSION_COOKIE_NAME = "I am Not session"2.在启动文件导入classfrom settings import DebugSettingsfrom settings import TestingSettings3.调用生效app.config.from_object(DebugSettings)# app.config.from_object(TestingSettings)
使用哪个就调用哪个,不使用注释掉即可
Flask 蓝图 Blueprint
- 当作是一个不能够被run的Flask对象(这样理解存在偏差),也没有config所以不能run
- 应用隔离
- 蓝图中不存在config
- 蓝图需要注册在app实例上app.register_blueprint()
-- url_prefix="" 路由前缀
test:
1.创建一个新的目录blue, 在目录下创建文件user.py 2.编辑user.pyfrom flask import Blueprintuser= Blueprint("user", __name__, url_prefix="/blue")@user.route("/index")def index():return "blue_index_user" 3.在启动文件中导入Blueprint实例userfrom blue.user import user 4.注册实例app.register_blueprint(user) 5.浏览器访问地址http://192.168.16.35:9999/index
Flask 特殊装饰器(类似中间件)
1.@app.before_request 请求进入视图函数之前进行处理
return None 继续执行, 否则阻断
@app.before_request # 请求进入视图函数之前 def before1():print('be1')return None# 登录验证 @home.before_request def is_login():if not session.get('username'):return redirect('/login')
2.@app.after_request 视图函数结束, 响应客户端之前
正常周期: beforef1 -> beforef2 -> vf -> afterf2 -> afterf1
异常周期: beforef1 -> afterf2 -> afterf1
3.errorhandler 重定义错误信息
1.有参数的装饰器errorhandler(监听错误状态码) 必须是int类型
2.所装饰的函数必须有一个形参来接收errormessage
@app.errorhandler(404) def error404(error_msg):print(error_msg)return "你要访问的页面不存在"
偷懒一下,使用redirect
@app.errorhandler(404) def error404(error_msg):print(error_msg)return redirect('https://www.bilibili.com/dsadsad')
使用send_file,可以传个图片,视频都是可以的哦
@app.errorhandler(404) def error404(error_msg):print(error_msg)return send_file('桌面.png')
注意:监听错误状态码 5xx 4xx ,是int类型的。200啦,还有302啥的都不可以!!!
错误信息总结
1. 蓝图实例与被装饰的函数不可重名
AttributeError: 'function' object has no attribute 'name'
2.两个文件之间循环导入
ImportError: cannot import name 'stu'
转载于:https://www.cnblogs.com/biao-wu/articles/11170564.html
Flask的路由、蓝图和装饰器相关推荐
- drf之day06:自动生成路由,action装饰器,登录接口的编写,局部认证,全局认证
目录标题 一:路由层知识点 1.自动生成路由 2.action装饰器的使用 二:登录接口的编写 三:认证 1.思路: 2.局部和全局认证 作业 一:路由层知识点 1.自动生成路由 只要继承了ViewS ...
- Flask中那些特殊的装饰器
模板相关的装饰器 @app.template_global() 用法: @app.template_global() # 记得加括号 def jiafa(a, b): # 这个方法每调用一次就需要传一 ...
- flask装饰器顺序
官方文档 To use the decorator, apply it as innermost decorator to a view function. When applying further ...
- Python装饰器-装饰流程,执行顺序
最近看到一个关于Flask的CTF(RealWorld CTF 2018 web题bookhub)文章 其中的一个trick是装饰器的顺序问题,就想写篇博客回顾下装饰器~ 首先强烈推荐很久之前看的一篇 ...
- Flask中路由使用解析
Flask简介 Flask是一个相对于Django而言轻量级的Web框架. 和Django大包大揽不同,Flask建立于一系列的开源软件包之上,这其中 最主要的是WSGI应用开发库Werkzeug和模 ...
- Flask框架——路由:URL规则与视图函数
1. 概述 路由 是MVC架构的Web框架中相当重要的一个概念,也是本节课程的重点.顾名思意,路由就是在迷茫中找出一条路的意思.在Flask框架中,路由 就表示为用户请求的URL找出其对应的处理函数之 ...
- Flask中路由系统以及蓝图的使用
一.Flask的路由系统 1.@app.route()装饰器中的参数 methods:当前URL地址,允许访问的请求方式 @app.route("/info", methods=[ ...
- 基于hi-nginx的web开发(python篇)——路由装饰器
现在,有了起步的基本认识,现在需要一个可以媲美flask或者bottle的简洁易用的路由功能,可以用装饰器写法任意映射 URLs 到代码. 这个,并不难.首先,来一个叫做hi的模块:hi.py: 1 ...
- python flask route中装饰器的使用
问题:route中的装饰器为什么感觉和平时使用的不太一样,装饰器带参数和不太参数有什么区别?被修饰的函数带参数和不带参数有什么区别? 测试1:装饰器不带参数,被修饰的函数也不带参数. def log( ...
- Python flask 特殊装饰器 @app.before_request 和 @app.after_request 以及@app.errorhandler介绍
特殊装饰器 @app.before_request 和 @app.after_request以及@app.errorhandler() 一.背景: Flask我们已经学习很多基础知识了,现在有一个问题 ...
最新文章
- 使用sublime text 执行 tcl 出错
- 鸿蒙os内测版应用名称,鸿蒙OS2.0发布,只有两款机型可以申请内测
- 一个老程序员的心里话(转载)
- std::ostringstream::str()返回临时对象
- IE7不能显示PNG
- 【干货】功能堆砌or视觉美观?看优秀PM如何权衡
- python 字符串大小写转换 其它不变_python字符串大小写如何转换
- 如何查看现有项目的struts和hibernate和spring版本
- log4net 使用手记
- python生成验证码的程序_Python基础篇生成4位随机验证码
- 都是第一,3143亿背后科技公司贡献了多少?
- My sql 存储过程实例
- XshellXftpPortable Xshell,Xftp便携版绿色版下载
- python向量运算_Python线性代数学习笔记——向量的基本运算,以及Python代码的实现...
- 0X00000000指令引用的0x00000000内存该内存不能为read或written
- Excel-DATEDIF函数计算两日期天数差
- PHP网页页脚咋设计,50个网页头部与网页页脚设计欣赏
- E.03.17 Lou Ottens, Father of Countless ==Mixtapes==, Is Dead at 94
- ACCV 结果出来了,大家来晒一晒吧~
- “健康童乐园”10000户落成促进乡村儿童身心智全面健康成长