Flask 信号和项目蓝图
信号(源码)
信号,是在flask框架中为我们预留的钩子,让我们可以进行一些自定义操作。
pip3 install blinker
根据flask项目的请求流程来进行设置扩展点
中间件
from flask import Flask, render_template
app = Flask(__name__, static_url_path='/yy')
@app.route('/index')
def index():
return render_template('img.html')
@app.route('/order')
def order():
return render_template('img.html')
class MyMiddleware(object):
def __init__(self, old_app):
self.wsgi_app = old_app.wsgi_app
def __call__(self, *args, **kwargs):
print('123')
result = self.wsgi_app(*args, **kwargs)
print('456')
return result
app.wsgi_app = MyMiddleware(app)
if __name__ == '__main__':
app.run()
* Serving Flask app '__main__'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
127.0.0.1 - - [20/May/2024 11:32:19] "GET / HTTP/1.1" 404 -
123
456
127.0.0.1 - - [20/May/2024 11:32:22] "GET /index HTTP/1.1" 200 -
127.0.0.1 - - [20/May/2024 11:32:22] "GET /yy/img/haha.png HTTP/1.1" 200 -
123
456
123
456
appcontext_pushed
当app_ctx被push到local中的栈之后,会触发appcontext_pushed信号,之前注册在这个信号中的方法,就会被执行。
from flask import Flask,render_template
from flask import signals
app = Flask(__name__, static_url_path='/yy')
@signals.appcontext_pushed.connect
def f1(arg):
print('appcontext_pushed信号f1被触发',arg)
@signals.appcontext_pushed.connect
def f2(arg):
print('appcontext_pushed信号f2被触发',arg)
@app.route('/')
def index():
return render_template('img.html')
@app.route('/order')
def order():
return render_template('img.html')
if __name__ == '__main__':
app.run()
# app.__call__
* Serving Flask app '__main__'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
127.0.0.1 - - [20/May/2024 11:54:29] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [20/May/2024 11:54:29] "GET /yy/img/haha.png HTTP/1.1" 304 -
appcontext_pushed信号f2被触发
appcontext_pushed信号f1被触发
appcontext_pushed信号f2被触发
appcontext_pushed信号f1被触发
执行before_first_request扩展
from flask import Flask,render_template
from flask import signals
app = Flask(__name__, static_url_path='/yy')
@signals.request_started.connect
def f3(arg):
print('request_started信号被触发',arg)
@app.route('/')
def index():
return render_template('img.html')
@app.route('/order')
def order():
return render_template('img.html')
if __name__ == '__main__':
app.run()
* Serving Flask app '__main__'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
127.0.0.1 - - [20/May/2024 11:57:32] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [20/May/2024 11:57:33] "GET /yy/img/haha.png HTTP/1.1" 304 -
request_started信号被触发
request_started信号被触发
url_value_processor
在请求之前被触发
from flask import Flask,render_template,g
from flask import signals
app = Flask(__name__, static_url_path='/yy')
@app.url_value_preprocessor
def f5(endpoint,args):
print('f5')
@app.route('/')
def index():
return render_template('img.html')
@app.route('/order')
def order():
return render_template('img.html')
if __name__ == '__main__':
app.run()
* Serving Flask app '__main__'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
127.0.0.1 - - [20/May/2024 11:59:28] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [20/May/2024 11:59:28] "GET /yy/img/haha.png HTTP/1.1" 304 -
request_started信号被触发
f5
request_started信号被触发
f5
before_reuqest
from flask import Flask,render_template,g
from flask import signals
app = Flask(__name__, static_url_path='/yy')
@app.before_request
def f6():
g.xx = 123
print('f6')
@app.route('/')
def index():
print('index')
return render_template('img.html')
if __name__ == '__main__':
app.run()
* Serving Flask app '__main__'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
127.0.0.1 - - [20/May/2024 14:49:58] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [20/May/2024 14:49:58] "GET /yy/img/haha.png HTTP/1.1" 304 -
f6
index
f6
视图函数
before_render_template / rendered_template
from flask import Flask,render_template,g
from flask import signals
app = Flask(__name__, static_url_path='/yy')
@signals.before_render_template.connect
def f7(app, template, context):
print('before_render_template f7 被触发')
@signals.template_rendered.connect
def f8(app, template, context):
print('template_rendered f8 被触发')
@app.route('/')
def index():
print('index')
return render_template('img.html')
if __name__ == '__main__':
app.run()
* Serving Flask app '__main__'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
127.0.0.1 - - [20/May/2024 15:01:57] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [20/May/2024 15:01:57] "GET /yy/img/haha.png HTTP/1.1" 304 -
index
before_render_template f7 被触发
template_rendered f8 被触发
after_request
from flask import Flask,render_template,g
from flask import signals
app = Flask(__name__, static_url_path='/yy')
@app.after_request
def f9(response):
print('after_request f9 被触发')
return response
@app.route('/')
def index():
print('index')
return render_template('img.html')
@app.route('/order')
def order():
print('order')
return render_template('img.html')
if __name__ == '__main__':
app.run()
* Serving Flask app '__main__'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
127.0.0.1 - - [20/May/2024 15:07:55] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [20/May/2024 15:07:55] "GET /yy/img/haha.png HTTP/1.1" 304 -
index
after_request f9 被触发
after_request f9 被触发
request_finished
from flask import Flask,render_template,g
from flask import signals
app = Flask(__name__, static_url_path='/yy')
@signals.request_finished.connect
def f10(app,response):
print('request_finished f10 被触发')
@app.route('/')
def index():
print('index')
return render_template('img.html')
@app.route('/order')
def order():
print('order')
return render_template('img.html')
if __name__ == '__main__':
app.run()
* Serving Flask app '__main__'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
127.0.0.1 - - [20/May/2024 15:09:16] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [20/May/2024 15:09:16] "GET /yy/img/haha.png HTTP/1.1" 304 -
index
request_finished f10 被触发
request_finished f10 被触发
got_request_exception
from flask import Flask,render_template,g
from flask import signals
app = Flask(__name__, static_url_path='/yy')
@app.before_first_request
def test():
int('asdf')
@signals.got_request_exception.connect
def f11(app,exception):
print('got_request_exception f11 被触发')
@app.route('/')
def index():
print('index')
return render_template('img.html')
@app.route('/order')
def order():
print('order')
return render_template('img.html')
if __name__ == '__main__':
app.run()
teardown_request
from flask import Flask,render_template,g
from flask import signals
app = Flask(__name__, static_url_path='/yy')
@app.teardown_request
def f12(exc):
print('teardown_request f12 被触发')
@app.route('/')
def index():
print('index')
return render_template('img.html')
@app.route('/order')
def order():
print('order')
return render_template('img.html')
if __name__ == '__main__':
app.run()
* Serving Flask app '__main__'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
127.0.0.1 - - [20/May/2024 15:12:13] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [20/May/2024 15:12:14] "GET /yy/img/haha.png HTTP/1.1" 304 -
index
teardown_request f12 被触发
teardown_request f12 被触发
request_tearing_down
from flask import Flask,render_template,g
from flask import signals
app = Flask(__name__, static_url_path='/yy')
@signals.request_tearing_down.connect
def f13(app,exc):
print('request_tearing_down f13 被触发')
@app.route('/')
def index():
print('index')
return render_template('img.html')
@app.route('/order')
def order():
print('order')
return render_template('img.html')
if __name__ == '__main__':
app.run()
* Serving Flask app '__main__'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
127.0.0.1 - - [20/May/2024 15:13:16] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [20/May/2024 15:13:16] "GET /yy/img/haha.png HTTP/1.1" 304 -
index
request_tearing_down f13 被触发
request_tearing_down f13 被触发
appcontext_popped
from flask import Flask,render_template,g
from flask import signals
app = Flask(__name__, static_url_path='/yy')
@signals.appcontext_popped.connect
def f14(app):
print('appcontext_popped f14 被触发')
@app.route('/')
def index():
print('index')
return render_template('img.html')
@app.route('/order')
def order():
print('order')
return render_template('img.html')
if __name__ == '__main__':
app.run()
* Serving Flask app '__main__'
* Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:5000
Press CTRL+C to quit
127.0.0.1 - - [20/May/2024 15:14:10] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [20/May/2024 15:14:10] "GET /yy/img/haha.png HTTP/1.1" 304 -
index
appcontext_popped f14 被触发
appcontext_popped f14 被触发
总结
总结:关于flask内部共有14+个扩展点用于我们对flask框架内部进行定制,其中有:9个是信号。
template_rendered = _signals.signal("template-rendered")
before_render_template = _signals.signal("before-render-template")
request_started = _signals.signal("request-started")
request_finished = _signals.signal("request-finished")
request_tearing_down = _signals.signal("request-tearing-down")
got_request_exception = _signals.signal("got-request-exception")
appcontext_tearing_down = _signals.signal("appcontext-tearing-down")
appcontext_pushed = _signals.signal("appcontext-pushed")
appcontext_popped = _signals.signal("appcontext-popped")
message_flashed = _signals.signal("message-flashed")
扩展:flash
flash存值之后只能取一次
from flask import Flask,render_template,flash,get_flashed_messages,session
from flask import signals
app = Flask(__name__, static_url_path='/yy')
app.secret_key = 'iuknsoiuwknlskjdf'
@app.route('/')
def index():
# flash('123')
session['k1'] = 123
return render_template('img.html')
@app.route('/order')
def order():
# messages = get_flashed_messages()
# print(messages)
val = session['k1']
del session['k1']
print('session k1:', val)
return render_template('img.html')
if __name__ == '__main__':
app.run()
flask-script
flask的组件,用于运行flask程序。
安装: pip3 install flask-script
from demo import create_app
from flask_script import Manager
app = create_app()
manager = Manager(app)
@manager.command
def custom(arg):
"""
自定义命令
python manage.py custom 123
:param arg:
:return:
"""
print(arg)
@manager.option('-n', '--name', dest='name')
@manager.option('-u', '--url', dest='url')
def cmd(name, url):
"""
自定义命令
执行: python manage.py cmd -n waws -u http://www.baidu.com
:param name:
:param url:
:return:
"""
print(name, url)
if __name__ == '__main__':
manager.run()
python manage.py cmd -n waws -u http://www.baidu.com
python manage.py custom 123
其他
结合:flask-migrate / flask-sqlalchemy
python manage.py migrate
蓝图
分功能蓝图(项目大)
- waws_project(项目)
- waws_project(蓝图)
- user(用户功能)
- static
- templates
- add_user.html
- views
- add_user.py
- remove_user.py
- __init__.py
- power(权限功能)
- static
- templates
- views
- add_power.py
- remove_power.py
- __init__.py
- ......
- __init__.py
- config
- settings.py
- manage.py
# user/__init__.py文件
from flask import Blueprint,render_template
# 蓝图中视图函数render_template默认会去蓝图根目录找模板文件,没有在去功能蓝图的templates下查找
user = Blueprint('user',__name__,template_folder='templates')
# 因为是从manage.py启动的文件,所以在注册蓝图的时候可以走到当前文件,但是无法和视图函数进行关联,所以需要在这个地方引入才行
from .view import add_user
# waws_project/__init__.py文件
from flask import Flask
def create_app():
app = Flask(__name__)
app.config.from_object('config.settings')
from .user import user
from .power import power
app.register_blueprint(user)
app.register_blueprint(power)
return app
# view/add_user.py
from .. import user
from flask import render_template
@user.route("/add_user")
def add_user():
return render_template("add_user.html")
分结构蓝图(项目中、小)
- waws_project(项目)
- waws_project(蓝图)
- static
- templates
- add_user.html
- views
- add_user.py
- remove_user.py
- __init__.py
- config
- settings.py
- manage.py