#flask里面的请求扩展相当于django中的中间件 from flask import Flask,request app = Flask(__name__) @app.before_request def before1(): print("我是befor1") return "ok" @app.before_request def before2(): print("我是befor2") @app.after_request def after1(response): print("响应后的参数",response) print("我是after1") return response @app.after_request def after2(response): print("我是after2") return response @app.before_first_request def first(): print("我是第一次") @app.route("/") def index(): print("我是响应函数") return "ok" if __name__ == '__main__': app.run()
1 before_first_request 当项目启动后,接收到的第一个请求,就会执行before_first_request装饰的函数,执行顺序也是谁先注册就谁先执行,无论有没有返回值,后面都会执行 2 before_request 请求没有经过响应函数的时候,会执行before_request装饰的函数,谁先注册谁先执行。只要有一个函数有返回值,后面的所有before_request都不会执行,且响应函数也不会执行。其有没有返回值都不会影响after_request的执行 3 after_request是再before_request与响应函数执行后执行。他必须接收响应参数,并且要把响应返回。执行顺序是谁先注册后执行。
from flask import Flask,request,render_template app = Flask(__name__) @app.teardown_request def tear(e): print(e) print("我是teardown_request") @app.errorhandler(500) def error_500(e): print(e) return "我程序崩了,你下次来把" @app.errorhandler(404) def error_404(e): print(e) return render_template("404.html") #相当于django中的标签。 @app.template_global() def get_sb(a1,a2): return a1 + a2 #再html中的用法{{get_sb(1,2)}} #django中的过滤器,以一个参数是你要过滤的那个值 @app.template_filter() def get_something(a1,a2,a3,a4): return a1+a2+a3+a4 #再html中{{1|4,2,3}} @app.route("/") def index(): print("我是响应函数") return render_template("index.html") if __name__ == '__main__': app.run()
总结
1 teardown_request,一旦遇到错误就会执行,并且把错误传递给teardown_request装饰的函数, 没有错误也会执行,但是是错误为None,他并不能处理错误,只能记录
2 errorhandle 可以捕获错误,并且对错误做出响应,返回给用户,如果你要用errorhandler你必须指定他捕获哪种类型的错误,就必须传错误码,然后就返回值,返回给用户
##了解的知识点 from flask import Flask app = Flask(__name__) class MyMiddleware: def __init__(self,old_wsgi_app): self.old_wsgi_app =old_wsgi_app def __call__(self, environ, start_response): #这befor的befor print("开始之前") ret = self.old_wsgi_app(environ, start_response) #这是after的after print("结束之后") return ret @app.route("/") def index(): return "ok" if __name__ == '__main__': app.wsgi_app = MyMiddleware(app.wsgi_app) app.run()
from flask import Flask,views,url_for app = Flask(__name__) def tt(func): def inner(*args,**kwargs): print("你追到我。。") rv = func(*args,**kwargs) print("嘿嘿嘿。。。") return rv return inner class Index(views.View): methods = ["GET"] #规定哪些请求方式可以请求我这个路由 decorators =[tt,] #这个是给 我们的响应添加装饰器 def dispatch_request(self): return "ojbk" app.add_url_rule("/index",view_func=Index.as_view(name="index"),endpoint="index1") # 为什么要给as_view传递name= "index", #1 as_view再语法就要你传, #2 他作用Index.as_view(name="index")他返回是的view这个函数对象,我们传递name="index"是给view的__name__改变名字。如果不传,我没有办法通过名字来找路由的映射关系,因为都是”view“
from flask import Flask,views,url_for app = Flask(__name__) def tt(func): def inner(*args,**kwargs): print("你追到我。。") rv = func(*args,**kwargs) print("嘿嘿嘿。。。") return rv return inner class Login(views.MethodView): methods = ["GET","POST"] # 规定哪些请求方式可以请求我这个路由 #decorators = [tt, ] # 这个是给 我们的响应添加装饰器 def get(self): print(url_for("index1")) return "get" def post(self): return "post" app.add_url_rule("/login",view_func=Login.as_view(name="login")) #实现方法是重写了dispatch_request,通过请求方法,来找到当前类中的函数。 if __name__ == '__main__': app.run()
# app01/__init__.py from flask import Flask app = Flask(__name__) from app01 import user # 导入路由 # app01/user.py from app01 import app @app.route('/user') def user(): return 'user' # manage.py from app01 import app if __name__ == '__main__': app.run()
使用蓝图,避免交叉导入问题
# app01/__init__.py from flask import Flask app = Flask(__name__) from app01 import user from app01 import order app.register_blueprint(user.us) # 注册蓝图 app.register_blueprint(order.ord) # app01/order.py from flask import Blueprint ord = Blueprint('/order',__name__) @ord.route('/order') def order(): return 'order' # app01/user.py from flask import Blueprint us = Blueprint('/user',__name__) @us.route('/user') def user(): return 'user' # manage.py from app01 import app if __name__ == '__main__': app.run()
# run.py from pro_flask import app if __name__ == '__main__': app.run() # pro_flask/__init__.py from flask import Flask app = Flask(__name__,template_folder='templates',static_folder='statics',static_url_path='/static') from .views.account import account from .views.blog import blog from .views.user import user @app.before_request # 所有app都执行 def befor1(): print("我是app的beforrequest") app.register_blueprint(account) app.register_blueprint(blog) app.register_blueprint(user) # pro_flask/views/user.py from flask import Blueprint user = Blueprint('us',__name__) #us为名称空间 @user.before_request # 针对user蓝图 def befor1(): print('我是us的befor1') @user.route('/user') def index(): return 'ok' # pro_flask/views/blog.py from flask import Blueprint,url_for blog = Blueprint('blog',__name__) # blog为名称空间, __name__为当前蓝图的所在文件 @blog.before_request # 针对blog蓝图 def befor1(): print("我是blog的befor1") @blog.route('/blog') def index(): print(url_for('us.index')) # 访问us名称空间中的index路径 return 'blog' # pro_flask/views/blog.py from flask import Blueprint from flask import render_template from flask import request account = Blueprint('account', __name__) @account.route('/login.html', methods=['GET', "POST"]) def login(): return render_template('login.html')
大型应用目录示例
# run.py from pro_flask import app if __name__ == '__main__': app.run() # pro_flask/__init__.py from flask import Flask from .admin import admin from .web import web app = Flask(__name__) app.debug = True app.register_blueprint(admin, url_prefix='/admin') # 只要访问吃蓝图,前面默认加上/admin前缀 app.register_blueprint(web) # pro_flask/admin/__init__.py from flask import Blueprint admin = Blueprint( 'admin', __name__, template_folder='templates', static_folder='static' ) from . import views # pro_flask/admin/views.py from . import admin @admin.route('/index') def index(): return 'Admin.Index' # pro_flask/web/__init__.py from flask import Blueprint web = Blueprint( 'web', __name__, template_folder='templates', static_folder='static' ) from . import views # pro_flask/web/views.py from . import web @web.route('/index') def index(): return 'Web.Index'
总结
1 @app.before_first_request,再项目启动后接收到的第一个请求,会执行before_first_request,他再@app.before_request之前执行。他也可以有多个,谁先注册谁先执行。无论有没有返回值,后面都会执行。 2 @app.before_request,再执行响应函数之前执行,他可以有多个,如果有多个谁先注册谁先执行,但是只要有一个有返回值,后面的before_request都会不执行,且响应函数也不执行。如果没有都befor_request返回值,那所有的before_request都会执行,且响应函数也会执行。 3 @app.after_request,再执行befor_request和响应之后执行,他可以有多个,如果有多个谁先注册谁后执行。被after_request装饰的函数,必须接收响应,且必须把响应对象返回。对于@pp.before_request有没有返回值,@app.after_request都会执行。 4@app.teardown_request,用来捕获错误,无论有没有错误都会执行。如果没有错误接收的错误就是none,如果有错误就会接收到错误。但是他不能处理错误。 5@app.errorhandler(500),用来捕获错误,捕获哪种错误,必须把错误的状态码传入到errorhandle中,如果没有错误就不会执行,如果有错误就能处理错误,给用户良好的体验。 6 @app.template_global(),相当于django中的标签,只要定义它,就可以再不把函数对象传递模板的情况下,再模板中直接使用。用法:{{函数名()}} 7 @app.template_filter(),相当于django中的过滤器,它使用和django中的过滤一样的用,但是它可以接收多个参数,无论是几个。用法:{{要过滤的值|函数名(参数)}}