作者会解释为什么,太需要了
…,we used a variable called request, it fells like the request is a global variable, but in reality, it is not.
If you consider your flask application in production, it will serve multiple clients at the same time, it is important that the request variable is correct for each thread that servering the request, so clearly request cannot be local variable because it will have different values to different threads.
The way flask handles this is to use the contexts.
书中是这样介绍的:
When Flask receives a request from the client, it needs to make a few objects available to the view function that handle it. A good example is the request object, which encapsulates the HTTP request sent by the client.
Flask uses contexts to temporaritly make certain objects globally accessible.
In reality, request cannot be a global variable if you consider that in a multithreaded server the threads are working on different requests from different clients at the same time, so each thread needs to see a different object in request. Contexts enables Flask to make certain variables globally accessible to a thread without interfering with the other threads.
Flask Web开发 中的翻译:
Flask 从客户端收到请求时,要让视图函数能访问一些对象,这样才能处理请求。请求对象就是一个很好的例子,它封装了客户端发送的HTTP 请求。
Flask 使用上下文临时把某些对象变为全局可访问。
事实上,request 不可能是全局变量。试想,在多线程服务器中,多个线程同时处理不同客户端发送的不同请求时,每个线程看到的request 对象必然不同。Falsk 使用上下文让特定的变量在一个线程中全局可访问,与此同时却不会干扰其他线程。
Session
视频中接着讲到了session
,跟着视频中的节奏写笔记。
it can be used to store data specific to that client.
session
变量中存储着一些用户信息,(比如用户名,从一个网页访问flask应用中的另一个网页,flask也能知道用户信息)
也需要secret_key
:
builtins.RuntimeError
RuntimeError: The session is unavailable because no secret key was set. Set the secret_key on the application to something unique and secret.
python代码:
from flask import Flask, render_template, session
app = Flask(__name__)
@app.route('/')
def index():
if 'count' not in session: #刚开始,session中没有count
session["count"] = 1 # 然后设置count = 1
else:
session["count"] += 1 # 每次刷新页面,count = count + 1
return render_template('index.html',count=session["count"]) #传递count参数(一个数字)到index.html中
if __name__ =="__main__":
app.secret_key = "For the session"
app.run(debug=True)
Request dispatching
视频中讲的比较概括,使用@app.route('/')
这个装饰器时绑定了/
和index
视图函数的映射关系。
然后服务器根据客户端请求的URL找到对应的视图函数,然后返回请求处理结果返回给客户端。
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
name = "FengWeilei"
return render_template("index.html",name=name)
if __name__ == '__main__':
app.run(debug=True)
app
是一个实例化的对象,可以从python中查看app
的一些属性
app.url_map
记录着路由和视图函数的映射关系。
/
指向index
,默认会使用HEAD
、OPTION
、GET
这些HTTP方法,(注意没有POST
)
/static/<filename>
路由是Flask 添加的特殊路由,用于访问静态文件。
- 还有
app.view_functions
。(Flask
源码中可以看到view_functions
是一个字典:self.view_functions = {}
,注意字典中key
不能重复,即不能有同名的视图函数)
Request hooks
视频中的介绍和书中的一样:
Sometimes it is useful to execute code before or after each request is processed. For example, at the start of each request it may be necessary to create a database connection, or authenticate the user making the request. Instead of duplicating the code that does this in every viewfunction, Flask gives you the option to register common functions to be invoked before or after a request is dispatched to a view function.
Request hooks are implemented as decorators. These are four hooks supported by Flask:
- before_first_request
- before_request
- after_request
- teardown_request
然后视频中的例子:
from flask import Flask, render_template, session, g
from datetime import datetime
app = Flask(__name__)
@app.before_request # 用户请求分发给视图函数处理之前,运行这个函数
def before_request(): # 写了一个函数,下面两个视图函数都能用。
if 'count' not in session:
session["count"] = 1
else:
session["count"] += 1
g.when = datetime.now().strftime('%H:%M:%S')
# g 一个应用上下文,来自 werkzeug。
# 简答介绍:An object that the application can use for temporary storage during the handling of request.
# This variable is reset with each request.
@app.route('/')
def index():
return render_template('index.html',count=session["count"], when=g.when)
@app.route('/same_index')
def same_index():
return render_template('same_index.html',count=session["count"], when=g.when)
if __name__ =="__main__":
app.secret_key = "For the session"
app.run(debug=True)
Responses
处理客户端请求,生成响应,都是在服务器中完成的。
app.run()
会创建本地服务器,在看不到的地方会有make_response()
方法,将视图函数的返回值变成真正的响应,返回给客户端。
比如在flask代码中直接使用这个make_response()
方法:
from flask import Flask, render_template, make_response
app = Flask(__name__)
@app.route('/response')
def response():
resp = make_response(render_template('text.txt'), 200 , {'Content-Type':'text/plain'})
# make_response可以接受三个参数,返回值内容、HTTP状态码、返回值类型的字典
return resp
if __name__ == "__main__":
app.secret_key = "For safety"
app.run(debug=True)
make_response()
或者说视图函数的返回值可以接受3个参数。
视图函数中返回值接收三个参数的例子(专心看这个响应,更多的网页元素以后再看):
此外,响应中还有400状态码、json
类型的响应、设置cookie等,视频中、书上都有介绍。