请求响应、session、闪现
请求和响应
from flask import Flask, request, render_template, redirect, make_response
app = Flask(__name__)
@app.route('/login.html', methods=['GET', "POST"])
def login():
return "登录"
if __name__ == '__main__':
app.run()
请求相关信息
# request.method # 请求方式
# request.args # 获取URL中的数据
# request.form # 存放FormData中的数据。FormData是对象,Form表单是标签,当提交的时候,Form表单的标签会变成FormData提交。在Ajax中只能使用FormData
# request.values # post和get请求中的所有参数组成的CombinedMultiDict,通常用来查看数据
# request.cookies # 获取cookie中的数据
# request.headers # 获取请求头
# request.path # 路由地址
# request.url # 访问的完整路径
# request.host_url # 将主机地址变成url http://127.0.0.1:5000/
# request.host # 主机地址 127.0.0.1:5000
响应相关信息
# return "字符串"
# return render_template('html模板路径',**{})
# return redirect('/index.html')
dic = {'k1':'v1'}
return json.dumps(dic)
return jsonify(dic)
# response = make_response(render_template('index.html'))
# response是flask.wrappers.Response类型
# response.delete_cookie('key')
# response.set_cookie('key', 'value')
# response.headers['X-Something'] = 'A value'
# return response
定制响应头的时候,可以封装到 make_response 中做操作
from flask import Flask, url_for, make_response
app = Flask(__name__)
@app.route('/index', methods=['GET', 'POST'])
def index():
obj = make_response('Index')
obj.headers['xxxx'] = '123'
return obj
if __name__ == '__main__':
app.run()
session
除请求对象之外,还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名。要使用会话,需要设置一个密钥。
- 设置:
session['username'] = 'xxx'
- 删除:
session.pop('username', None)
# 基本使用
from flask import Flask, session, redirect, url_for, escape, request
app = Flask(__name__)
@app.route('/')
def index():
if 'username' in session:
return 'Logged in as %s' % escape(session['username'])
return 'You are not logged in'
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
session['username'] = request.form['username']
return redirect(url_for('index'))
return '''
<form action="" method="post">
<p><input type=text name=username>
<p><input type=submit value=Login>
</form>
'''
@app.route('/logout')
def logout():
# remove the username from the session if it's there
session.pop('username', None)
return redirect(url_for('index'))
# set the secret key. keep this really secret:
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
闪现
有一个需求,一个值只能取一次
from flask import Flask, session
app = Flask(__name__)
app.secret_key = "dghsagvds"
@app.route('/set')
def set():
session['name'] = '湫兮如风'
return "SET..."
# 只能取一次
@app.route('/get')
def get():
name = session.pop("name")
print(name)
return "GET..."
if __name__ == '__main__':
app.run()
再取一次就会报错
闪现可以完成这个需求
from flask import Flask, flash, get_flashed_messages
app = Flask(__name__)
app.secret_key = "dghsagvds"
@app.route('/set')
def set():
flash('湫兮如风')
return "SET..."
# 只能取一次
@app.route('/get')
def get():
name = get_flashed_messages()
print(name)
return "GET..."
if __name__ == '__main__':
app.run()
from flask import Flask, flash, get_flashed_messages
app = Flask(__name__)
app.secret_key = "dghsagvds"
@app.route('/set')
def set():
flash('湫兮', "name")
flash('如风')
return "SET..."
# 只能取一次
@app.route('/get')
def get():
name = get_flashed_messages()
print(name)
return "GET..."
if __name__ == '__main__':
app.run()
from flask import Flask, flash, get_flashed_messages
app = Flask(__name__)
app.secret_key = "dghsagvds"
@app.route('/set')
def set():
# session['name'] = '湫兮如风'
flash('湫兮', "name")
flash('如风')
return "SET..."
# 只能取一次
@app.route('/get')
def get():
name = get_flashed_messages(category_filter=["name"])
print(name)
return "GET..."
if __name__ == '__main__':
app.run()
中间件
from flask import Flask
app = Flask(__name__)
if __name__ == '__main__':
app.run()
app.run() 执行的是 run_simple(host, port, self, **options)
run_simple 执行 self()
self 是 app
执行 self() 就是执行 app(),就是在执行 app 的 __call__ 方法,也就是 Flask 类里面的 __call__
def __call__(self, environ, start_response):
"""The WSGI server calls the Flask application object as the
WSGI application. This calls :meth:`wsgi_app` which can be
wrapped to applying middleware."""
return self.wsgi_app(environ, start_response)
environ
是请求来的所有最原生的数据,start_response
是封装响应对象的。flask 的任何请求都从这里开始,想添加中间件,都从这里的 return
之前或之后进行添加。
当然,不可能直接在源码中进行修改,可以自己重写
from flask import Flask
app = Flask(__name__)
class Middleware(object):
def __init__(self, old):
self.old = old
def __call__(self, *args, **kwargs):
# 旧的 wsgi_app()
return self.old(*args, **kwargs)
app.wsgi_app = Middleware(app.wsgi_app)
if __name__ == '__main__':
app.run()
# app.run() 就是在执行 app.__call__,返回 return self.wsgi_app()
# 这里的 self 就是 app 自己,所以 self.wsgi_app 就是上面写的 app.wsgi_app
# 上面写的 app.wsgi_app 是 Middleware()
# 所以这里 self.wsgi_app() 就是 Middleware()()
# 会走它的 __call__ 方法,返回 return self.old(*args, **kwargs)
# 这里的 self 是传过去的 app.wsgi_app,是去源码中查找 wsgi_app 并执行
引入一个装饰器的知识点
import functools
def auth(func):
@functools.wraps(func)
def inner(*args, **kwargs):
ret = func(*args, **kwargs)
return ret
return inner
@auth
def my_func():
return "my func"
@auth
def my_tools():
return "my tools"
print(my_func.__name__) # my_func
print(my_tools.__name__) # my_tools
针对于前面的登录 Demo,就可以使用装饰器而不必在每个功能下面都加上 session 的判断了
但是当接口多了起来,在每个接口下都加上 @auth
也不太现实,所以可以放在中间件里。
有一个装饰器叫做 @app.before_request
,它的作用是任何视图函数的请求进来都要先执行这个装饰器函数,这就和 Django 中间件里的 process_request
类似,如果有返回值,直接返回给用户,如果没有返回值,才执行下面的视图函数。
@app.before_request
def authentication():
if request.path == "/login":
return None
if session.get('user_info'):
return None
return redirect('/login')