请求扩展
from flask import Flask,render_template
app=Flask(__name__)
'''
@app.before_request:
是在真正的响应函数之前执行。
可以有多个,当有多个的时候执行顺序是谁在前面就谁先执行
只要有一个before_request有返回值,那么后面所有的before_request都不会执行,真正的响应函数也不会执行
'''
@app.before_request
def befor_process():
print("befor_process0")
# return "tt"
@app.before_request
def befor_process1():
print("befor_process1")
'''
@app.after_request:
after_request是在真正响应函数之后执行的。
他可以有多个,当有多个的时候执行顺序为,谁在前面谁后执行。
before_request的有没有返回值不会影响到after_request的执行
'''
@app.after_request
def after_process(response):
print("我是请求之后1")
return response
@app.after_request
def after_process1(response):
print("我是请求之后2")
return response
'''
@app.before_first_request:
在项目启动后第一次接收到请求,就会执行这个方法。以后不会执行
'''
@app.before_first_request
def first():
print(123)
'''
@app.teardown_request:
不管有没有错误,都会执行teardown_request
如果没有错误,错误值为None,如果有错误,直接传递给被装饰的函数
'''
@app.teardown_request
def tre(e):
print("e",e)
'''
@app.errorhandler(错误码):
如果没有该错误码出现,地下的函数不会执行,如果有该错误码的错误出现就会执行下面的函数,不会让错误暴露给用户
'''
@app.errorhandler(500)
def error_handler(*args,**kwargs):
print(*args,**kwargs)
return "500错误"
@app.errorhandler(404)
def errr(e):
return render_template("index404.html")
'''
@app.template_global():
标签 可以在路由返回的页面中使用 全局的 都可以使用
'''
@app.template_global()
def sb(a1,a2,a3):
return a1+a2+a3
'''
@app.template_filter():
过滤器 可以在路由返回的页面中使用 全局的 都可以使用
'''
@app.template_filter()
def sb1(a1,a2,a3):
return a1+a2+a3
@app.route("/index")
def index():
print("index")
return render_template("index.html")
if __name__ == '__main__':
app.run()
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>okok</h1>
<h1>{{sb(1,2,3)}}</h1>
<h1>{{"tank"|sb1(" is ","sb")}}</h1>
</body>
</html>
index404.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>404错误页面</h1>
</body>
</html>
中间件
'''
1 当执行app.run()方法的时候,最终执行run_simple,最后执行app(),也就是在执行app.__call__方法
2 在__call__里面,执行的是self..wsgi_app(),那么希望在执行他本身的wsgi之前做点事情
3 所有我们先用MyMiddleware类中__init__,保存之前的wsgi,然后我们将app.wsgi转化成MyMiddleware的对象
4 把原来的wsgi.app替换为自定义的
'''
from flask import Flask
app=Flask(__name__)
class MyMiddleware(object):
def __init__(self,old_wsgi_app):
self.old_wsgi_app=old_wsgi_app
def __call__(self, environ, start_response):
print("123")
ret=self.old_wsgi_app(environ, start_response)
print("456")
return ret
@app.route('/')
def index():
return "ok"
if __name__ == '__main__':
app.wsgi_app=MyMiddleware(app.wsgi_app)
app.run()
偏函数
将所作用的函数作为partial()函数的第一个参数,原函数的各个参数依次作为partial()函数的后续参数,原函数有关键字参数的一定要带上关键字,没有的话,按原有参数顺序进行补充。
简单总结functools.partial的作用就是,把一个函数的某些参数给固定住(也就是设置默认值),返回一个新的函数,调用这个新函数会更简单。
from functools import partial
def test(a,b,c):
return a+b+c
tes=partial(test,1,2,4)
#用partial可以得到一个带了参数的函数对象
print(tes())
tes1=partial(test,1,2)
print(tes1(c=5))
蓝图
-app01
--__init__.py
--order.py
--user.py
-run.py
init.py
from flask import Flask
app=Flask(__name__)
from app01 import user
from app01 import order
@app.before_request
def tt1():
print("我是app的befor——request")
app.register_blueprint(user.us)
app.register_blueprint(order.ord)
order.py
from flask import Blueprint
ord=Blueprint("order",__name__)
@ord.route("/order")
def order():
return "order"
user.py
from flask import Blueprint,url_for
us=Blueprint("user",__name__)
@us.before_request
def beofor_req():
print("我是user里面的befor_request")
@us.route("/user")
def index():
print(url_for("user.order"))
print(url_for("order.order"))
return "index"
@us.route("/tt")
def order():
return "455"
run.py
from app01 import app
if __name__ == '__main__':
app.run()
loacal对象的补充
# 启动一个多线程,多线程修改一个全局的值,并且要求打印,它自己修改成功之后的那个值
from threading import Thread
import time
from threading import local
# 利用local
'''
cxw = local()
def task(arg):
cxw.value = arg
# cxw[线程id][value]=arg
time.sleep(1)
# cxw[线程id][value]
print(cxw.value)
'''
from threading import get_ident
# 用函数的形式模拟local()对象
'''
storage={}
def set(k,v):
ident=get_ident()
if ident in storage:
storage[ident][k]=v
else:
storage[ident]={k:v}
def get(k):
ident=get_ident()
return storage[ident][k]
def task(arg):
set("val",arg)
time.sleep(1)
v=get('val')
print(v)
'''
# 面向对象版
'''
class Local:
storage = {}
def set(self,k,v):
ident = get_ident()#获取线程协程的id
if ident in Local.storage:
Local.storage[ident][k] = v
else:
Local.storage[ident] = {k: v}
def get(self,k):
ident = get_ident()
return Local.storage[ident][k]
obj=Local()
def task(arg):
obj.set("val", arg)
time.sleep(1)
v = obj.get('val')
print(v)
'''
# 面向对象版的getattr和setattr实现,,每个local对象都有他自己的storage
class Local(object):
def __init__(self):
object.__setattr__(self, "storage", {})
# storage={}
def __setattr__(self, k, va):
ident = get_ident()
if ident in self.storage:
self.storage[ident][k] = va
else:
self.storage[ident] = {k: va}
def __getattr__(self, k):
ident = get_ident()
return self.storage[ident][k]
obj = Local()
def task(arg):
obj.va = arg
time.sleep(1)
print(obj.va)
for i in range(10):
t = Thread(target=task, args=(i,))
t.start()
请求上下文
1 执行 ctx = self.request_context(environ) 将请求相关的放入ctx
2 ctx.push 方法,把cxt放入到Local对象中的stroage[线程或者协程id][stark]=[ctx,]
3 response = self.full_dispatch_request()这个是请求扩展和响应函数的内容
4 在上述的3中我们可以在任意位置调用 resquest
5 当我们调用request.methons的时候是怎么获取到的?从第二步中存的Local把ctx取出来
6 在ctx在取request
7 然后再从request取methons