Loading

请求响应、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')

posted @ 2020-02-20 09:03  湫兮  阅读(290)  评论(0编辑  收藏  举报