Flask Markup 上下文,request
在模板渲染中,使用Markup转换变量中的特殊字符
from flask import Markup
Markup函数对字符串进行转移处理再传递给render_template()函数
在浏览器中显示标签代码
路由地址的反响生成
通过函数名获得与其绑定的Url地址
需要使用url_for函数进行反向解析
with app.text_request_context()
print(url_for('f_root')) # 输出:/
app.text_request_context()方法告诉解释器为在其作用域中的代码模拟一个HTTP请求上下文,使其好像被一个HTTP请求所调用 使用Context上下文
他是服务器端获得应用及请求相关信息的对象
1、会话上下文
会话(session)是一种客户端与服务器端保持状态的解决方案,会话上下文是用来实现这种解决方案的存储结构
from flask import Flask,session
from datetime import datetime app = Flask(__name__) app.secret_key = 'SET_ME_BEFORE_USE_SESSION' @app.route('/')
def hello_world():
return 'Hello World!' @app.route('/write_session')
def wirteSession():
session['key_time']=datetime.now().strftime('%Y-%m-%d %H:%M:%S')# 将当前时间保存在Session中
return session['key_time'] # 返回当前时间
@app.route('/read_session')
def readSession():
return session.get('key_time')# 获取上次调用wirteSession时写入的时间并返回
除了正常的数据保存和读取,flask.session对象还维护自身的状态,通过
new 判断本次请求的Session是否时新建的
modified 判断本次请求中是否修改过Session键值
@app.route('/write_session')
def wirteSession():
session['key_time']=time.time() # 将当前时间保存在Session中
return session.modified # 因为之前进行了Session设置,所以判断本次请求是否被修改过(modified)返回TRUE
应用全局对象
from flask import Flask,g class MYDB():
def __init__(self):
print('一个数据库链接已经建立') def close(self):
print('数据库已经关闭') def connect_to_database():
return MYDB() def get_db():
db = getattr(g,'_database',None)
if db is None:
db = connect_to_database()
g._database = db # 存入Flask.g对象中
return db @app.teardown_request # 在请求结束时自动被Flask框架调用
def teardown_db(response):
db = getattr(g,'_database',None)# 从Flask.g对象中获取对象,检查是否有链接数据库对象,如果有则关闭
if db is not None:
db.close()
可以在请求处理函数的任何地方调用get_db()
class MYDB():
def __init__(self):
print('一个数据库链接已经建立') def close(self):
print('数据库已经关闭') def connect_to_database():
return MYDB() def get_db():
db = getattr(g,'_database',None)
if db is None:
db = connect_to_database()
g._database = db # 存入Flask.g对象中
return db @app.teardown_request
def teardown_db(response):
db = getattr(g,'_database',None)# 从Flask.g对象中获取对象
if db is not None:
db.close()
def login():
db=get_db() # 第一次调用getdb 创建数据库链接
session['has_login']=True
# 使用db检查数据库中的用户名和密码
def view_list():
if 'has_login' not in session:
login()
db = get_db() # 第二次调用get_db()# 直接复用之前建立的链接
# 使用db 从数据库查询数据,返回teardown_db()将会被自动调用
请求上下文生命周期
from flask import Flask, g, request app = Flask(__name__) @app.before_request
def before_request():
print 'before request started'
print request.url @app.before_request
def before_request2():
print 'before request started 2'
print request.url
g.name="SampleApp" @app.after_request
def after_request(response):
print 'after request finished'
print request.url
response.headers['key'] = 'value'
return response @app.teardown_request
def teardown_request(exception):
print 'teardown request'
print request.url @app.route('/')
def index():
return 'Hello, %s!' % g.name if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)
访问”http://localhost:5000/”后,会在控制台输出:
before request started
http://localhost:5000/
before request started 2
http://localhost:5000/
after request finished
http://localhost:5000/
teardown request
http://localhost:5000/
request对象只有在请求上下文的生命周期内才可以访问。离开了请求的生命周期,其上下文环境也就不存在了,自然也无法获取request对象。而上面介绍的几个由上下文装饰器修饰的Hook函数,会挂载在请求生命周期内的不同阶段,所以其内部可以访问request对象。
构建请求上下文环境
我们使用Flask的内部方法”request_context()”来构建一个客户端请求上下文。
from werkzeug.test import EnvironBuilder
ctx = app.request_context(EnvironBuilder('/','http://localhost/').get_environ())
ctx.push()
try:
print request.url
finally:
ctx.pop()
“request_context()”会创建一个请求上下文”RequestContext”类型的对象,其需接收”werkzeug”中的”environ”对象为参数。”werkzeug”是Flask所依赖的WSGI函数库
我们可以在客户端的请求之外访问request对象,其实此时的request对象即是刚创建的请求上下文中的一个属性”request == ctx.request”。启动Flask时,控制台仍然可以打印出访问地址”http://localhost/”。上面的代码可以用with语句来简化:
from werkzeug.test import EnvironBuilder
with app.request_context(EnvironBuilder('/','http://localhost/').get_environ()):
print request.url
请求上下文的实现方式
对于Flask Web应用来说,每个请求就是一个独立的线程。请求之间的信息要完全隔离,避免冲突,这就需要使用本地线程环境(ThreadLocal),
”ctx.push()”方法,会将当前请求上下文,压入”flask._request_ctx_stack”的栈中,同时这个”_request_ctx_stack”栈是个ThreadLocal对象,也就是”flask._request_ctx_stack”看似全局对象,其实每个线程的都不一样。请求上下文压入栈后,再次访问其都会从这个栈的顶端通过”_request_ctx_stack.top”来获取,所以取到的永远是只属于本线程中的对象,这样不同请求之间的上下文就做到了完全隔离。请求结束后,线程退出,ThreadLocal线程本地变量也随即销毁,”ctx.pop()”用来将请求上下文从栈里弹出,避免内存无法回收。
——————————————————————————————————————————————————————————————————————
主要是在服务端获得从客户端提交的数据,包括url参数,表单数据,cookies等
from flask import Flask,request,url_for,redirect
app = Flask(__name__)
@app.route('/redirect_url')
def redirect_url():
next = request.args.get('next') or url_for('index')
return redirect(next)
@app.route('/echo_url')
def echo_url():
return request.base_url
自定义上下文变量和函数
自定义变量
from flask import current_app @app.context_processor
def appinfo():
return dict(appname=current_app.name)
函数返回的是一个字典,里面有一个属性”appname”,值为当前应用的名称。我们曾经介绍过,这里的”current_app”对象是一个定义在应用上下文中的代理。函数用”@app.context_processor”装饰器修饰,它是一个上下文处理器,它的作用是在模板被渲染前运行其所修饰的函数,并将函数返回的字典导入到模板上下文环境中,与模板上下文合并。然后,在模板中”appname”成为了可访问的上下文对象。我们可以在模板中将其输出:
<p>Current App is: {{ appname }}</p>
自定义函数
同理我们可以自定义上下文函数,只需将上例中返回字典的属性指向一个函数即可,下面我们就来定义一个上下文函数来获取系统当前时间:
import time @app.context_processor
def get_current_time():
def get_time(timeFormat="%b %d, %Y - %H:%M:%S"):
return time.strftime(timeFormat)
return dict(current_time=get_time)
<p>Current Time is: {{ current_time() }}</p>
<p>Current Day is: {{ current_time("%Y-%m-%d") }}</p>
应用上下文环境
current_app代理
from flask import Flask, current_app
app = Flask('SampleApp')
@app.route('/')
def index():
return 'Hello, %s!' % current_app.name
我们可以通过”current_app.name”来获取当前应用的名称,也就是”SampleApp”。”current_app”是一个本地代理,它的类型是”werkzeug.local. LocalProxy”,它所代理的即是我们的app对象,也就是说”current_app == LocalProxy(app)”。使用”current_app”是因为它也是一个ThreadLocal变量,对它的改动不会影响到其他线程。你可以通过”current_app._get_current_object()”方法来获取app对象。
既然是ThreadLocal对象,那它就只在请求线程内存在,它的生命周期就是在应用上下文里。离开了应用上下文,”current_app”一样无法使用
构建应用上下文环境
同请求上下文一样,我们也可以手动构建应用上下文环境:
with app.app_context():
print current_app.name
“app_context()”方法会创建一个”AppContext”类型对象,即应用上下文对象,此后我们就可以在应用上下文中,访问”current_app”对象了。
应用上下文Hook函数
应用上下文也提供了装饰器来修饰Hook函数,不过只有一个”@app.teardown_appcontext”。它会在应用上下文生命周期结束前,也就是从”_app_ctx_stack”出栈时被调用。我们可以加入下面的代码,顺便也验证下,是否应用上下文在每个请求结束时会被销毁。
@app.teardown_appcontext
def teardown_db(exception):
print 'teardown application'
request的属性
下面是request可使用的属性,其中黑体是比较常用的。
form
一个从POST和PUT请求解析的 MultiDict(一键多值字典)。args
MultiDict,要操作 URL (如 ?key=value )中提交的参数可以使用 args 属性:
searchword = request.args.get('key', '')
values
CombinedMultiDict,内容是form和args。
可以使用values替代form和args。cookies
顾名思义,请求的cookies,类型是dict。stream
在可知的mimetype下,如果进来的表单数据无法解码,会没有任何改动的保存到这个·stream·以供使用。很多时候,当请求的数据转换为string时,使用data是最好的方式。这个stream只返回数据一次。headers
请求头,字典类型。data
包含了请求的数据,并转换为字符串,除非是一个Flask无法处理的mimetype。files
MultiDict,带有通过POST或PUT请求上传的文件。environ
WSGI隐含的环境配置。method
请求方法,比如POST、GET。path
- script_root
- url
- base_url
- url_root
如果用户请求如下URL:http://www.example.com/myapplication/page.html?x=y
以上的参数内容如下:
| 名称 | 内容 |
|---|---|
| path | /page.html |
| script_root | /myapplication |
| base_url | http://www.example.com/myapplication/page.html |
| url | http://www.example.com/myapplication/page.html?x=y |
| url_root | http://www.example.com/myapplication/ |
is_xhr
如果请求是一个来自JavaScript XMLHttpRequest的触发,则返回True,这个只工作在支持X-Requested-With头的库并且设置了XMLHttpRequest。blurprint
蓝本名字。endpoint
endpoint匹配请求,这个与view_args相结合,可是用于重构相同或修改URL。当匹配的时候发生异常,会返回None。get_json(force=False, silent=False, cache=True)
json
如果mimetype是application/json,这个参数将会解析JSON数据,如果不是则返回None。
可以使用这个替代get_json()方法。max_content_length
只读,返回MAX_CONTENT_LENGTH的配置键。module
如果请求是发送到一个实际的模块,则该参数返回当前模块的名称。这是弃用的功能,使用blueprints替代。- on_json_loading_failed(e)
routing_exception = None
如果匹配URL失败,这个异常将会/已经抛出作为请求处理的一部分。这通常用于NotFound异常或类似的情况。url_rule = None
内部规则匹配请求的URL。这可用于在URL之前/之后检查方法是否允许(request.url_rule.methods) 等等。
默认情况下,在处理请求函数中写下print('request.url_rule.methods', request.url_rule.methods)
会打印:request.url_rule.methods {‘GET’, ‘OPTIONS’, ‘HEAD’}
view_args = None
一个匹配请求的view参数的字典,当匹配的时候发生异常,会返回None。
Flask Markup 上下文,request的更多相关文章
- Flask请求上下文request
- 深入flask中的request
缘起 在使用flask的时候一直比较纳闷request是什么原理,他是如何保证多线程情况下对不同请求参数的隔离的. 准备知识 在讲request之前首先需要先理解一下werkzeug.local中的几 ...
- Flask(4)- flask请求上下文源码解读、http聊天室单聊/群聊(基于gevent-websocket)
一.flask请求上下文源码解读 通过上篇源码分析,我们知道了有请求发来的时候就执行了app(Flask的实例化对象)的__call__方法,而__call__方法返回了app的wsgi_app(en ...
- flask 的上下文管理
Flask的上下文对象 Flask有两种Context(上下文),分别是 RequestContext 请求上下文 Request 请求的对象,封装了Http请求(environ)的内容 Sessio ...
- Flask的上下文管理机制
前引 在了解flask上下文管理机制之前,先来一波必知必会的知识点. 面向对象双下方法 首先,先来聊一聊面向对象中的一些特殊的双下划线方法,比如__call__.__getattr__系列.__get ...
- flask 请求上下文源码(转)
本篇阅读目录 一.flask请求上下文源码解读 二.http聊天室(单聊/群聊)- 基于gevent-websocket 回到顶部 转:https://www.cnblogs.com/li-li/p/ ...
- Flask中的request模板渲染Jinja以及Session
Flask中的request与django相似介绍几个常用的以后用的时候直接查询即可 1.request from flask import request(用之前先引用,与django稍有不同) r ...
- flask框架上下文
上下文 上下文:相当于一个容器,保存了 Flask 程序运行过程中的一些信息. Flask中有两种上下文,请求上下文和应用上下文 请求上下文(request context) 在 flask 中,可以 ...
- 第三篇 Flask 中的 request
第三篇 Flask 中的 request 每个框架中都有处理请求的机制(request),但是每个框架的处理方式和机制是不同的 为了了解Flask的request中都有什么东西,首先我们要写一个前 ...
随机推荐
- [BZOJ4736]温暖会指引我们前行
BZOJ(BZOJ上的是什么鬼...) UOJ 任务描述 虽然小R住的宿舍楼早已来了暖气,但是由于某些原因,宿舍楼中的某些窗户仍然开着(例如厕所的窗户),这就使得宿舍楼中有一些路上的温度还是很低. 小 ...
- Poj3683:Priest John's Busiest Day
题意 n对夫妻要结婚,第i对夫妻结婚的婚礼持续时间为[Si, Ti],他们会举行一个仪式,仪式时间为Di,这个仪式只能举行在开头或者结尾举行,要么[Si, Si+Di],要么[Ti-Di, Ti],然 ...
- THUWC2018咸鱼记
Day -inf 好不容易联赛水进来了 好虚啊...(萌新)什么都不会...只会大水题 估计要\(GG\)了,瑟瑟发抖 准备辣.. 自我介绍根本没面试,就没脸贴了 周围的大佬们(尤其\(Zsy\))还 ...
- iBrand 教程 0.1:Windows + Homestead 5 搭建 Laravel 开发环境
统一开发环境 为了保证在学习和工作过程中避免因为开发环境不一致而导致各种各样的问题,Laravel 官方为了我们提供了一个完美的开发环境 Laravel Homestead,让我们无需再本地安装 PH ...
- Java求最大公约数和最小公倍数
最大公约数(Greatest Common Divisor(GCD)) 基本概念 最大公因数,也称最大公约数.最大公因子,指两个或多个整数共有约数中最大的一个.a,b的最大公约数记为(a,b),同样的 ...
- 【xsy2115】Delight for a Cat
Time Limit: 1000 ms Memory Limit: 512 MB Description 从前,有一只懒猫叫CJB.每个小时,这只猫要么在睡觉,要么在吃东西,但不能一边睡觉一边吃东 ...
- JBox使用详解
插件说明 - jBox 是一款基于 jQuery 的多功能对话框插件,能够实现网站的整体风格效果,给用户一个新的视觉享受. 运行环境 - 兼容 IE6+.Firefox.Chrome.Safari.O ...
- java如何输入数据
Java程序开发过程中,需要从键盘获取输入值是常有的事,但Java它偏偏就没有像c语言给我们提供的scanf(),C++给我们提供的cin()获取键盘输入值的现成函数!Java没有提供这样的函数也不代 ...
- 深入理解JVM垃圾收集机制(JDK1.8)
垃圾收集算法 标记-清除算法 最基础的收集算法是"标记-清除"(Mark-Sweep)算法,分两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象. 不足: ...
- Python多线程爬虫与多种数据存储方式实现(Python爬虫实战2)
1. 多进程爬虫 对于数据量较大的爬虫,对数据的处理要求较高时,可以采用python多进程或多线程的机制完成,多进程是指分配多个CPU处理程序,同一时刻只有一个CPU在工作,多线程是指进程内部有多个类 ...