版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27695659/article/details/88739733
1. 路由和视图
a. 路由设置的两种方式:
@app.route('/xxx')
def index():
return "index"
def index():
return "index"
app.add_url_rule("/xxx",None,index)
注意事项:
- 不用让endpoint重名
- 如果重名函数也一定要相同。
b. 参数
rule, URL规则
view_func, 视图函数名称
endpoint=None, 名称,用于反向生成URL,即: url_for('名称')
methods=None, 允许的请求方式,如:["GET","POST"]
strict_slashes=None, 对URL最后的 / 符号是否严格要求,
redirect_to=None, 重定向到指定地址
defaults=None, 默认值,当URL中无参数,函数需要参数时,使用defaults={'k':'v'}为函数提供参数
subdomain=None, 子域名访问
c. CBV
import functools
from flask import Flask,views
app = Flask(__name__)
def wrapper(func):
@functools.wraps(func)
def inner(*args,**kwargs):
return func(*args,**kwargs)
return inner
class UserView(views.MethodView):
methods = ['GET']
decorators = [wrapper,]
def get(self,*args,**kwargs):
return 'GET'
def post(self,*args,**kwargs):
return 'POST'
app.add_url_rule('/user',None,UserView.as_view('uuuu'))
if __name__ == '__main__':
app.run()
d. 自定义正则
from flask import Flask,url_for
app = Flask(__name__)
# 步骤一:定制类
from werkzeug.routing import BaseConverter
class RegexConverter(BaseConverter):
"""
自定义URL匹配正则表达式
"""
def __init__(self, map, regex):
super(RegexConverter, self).__init__(map)
self.regex = regex
def to_python(self, value):
"""
路由匹配时,匹配成功后传递给视图函数中参数的值
:param value:
:return:
"""
return int(value)
def to_url(self, value):
"""
使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数
:param value:
:return:
"""
val = super(RegexConverter, self).to_url(value)
return val
# 步骤二:添加到转换器
app.url_map.converters['reg'] = RegexConverter
"""
1. 用户发送请求
2. flask内部进行正则匹配
3. 调用to_python(正则匹配的结果)方法
4. to_python方法的返回值会交给视图函数的参数
"""
# 步骤三:使用自定义正则
@app.route('/index/<reg("\d+"):nid>')
def index(nid):
print(nid,type(nid))
print(url_for('index',nid=987))
return "index"
if __name__ == '__main__':
app.run()
2. session实现原理(源码)
3. 蓝图
目标:给开发者提供目录结构
其他:
- 自定义模板、静态文件
- 某一类url添加前缀
- 给一类url添加before_request
4. threading.local【和flask无任何关系】
作用:为每个线程创建一个独立的空间,使得线程对自己的空间中的数据进行操作(数据隔离)。
import threading
from threading import local
import time
obj = local()
def task(i):
obj.xxxxx = i
time.sleep(2)
print(obj.test,i)
for i in range(10):
t = threading.Thread(target=task,args=(i,))
t.start()
问题:
- 如何获取一个线程的唯一标记? threading.get_ident()
- 根据字典自定义一个类似于threading.local功能?
import time
import threading
DIC = {}
def task(i):
ident = threading.get_ident()
if ident in DIC:
DIC[ident]['test'] = i
else:
DIC[ident] = {'test':i }
time.sleep(2)
print(DIC[ident]['test'],i)
for i in range(10):
t = threading.Thread(target=task,args=(i,))
t.start()
- 根据字典自定义一个为每个协程开辟空间进行存取数据。
import time
import threading
import greenlet
DIC = {}
def task(i):
# ident = threading.get_ident()
ident = greenlet.getcurrent()
if ident in DIC:
DIC[ident]['test'] = i
else:
DIC[ident] = {'test':i }
time.sleep(2)
print(DIC[ident]['test'],i)
for i in range(10):
t = threading.Thread(target=task,args=(i,))
t.start()
- 通过getattr/setattr 构造出来 threading.local的加强版(协程)
import time
import threading
try:
import greenlet
get_ident = greenlet.getcurrent
except Exception as e:
get_ident = threading.get_ident
class Local(object):
DIC = {}
def __getattr__(self, item):
ident = get_ident()
if ident in self.DIC:
return self.DIC[ident].get(item)
return None
def __setattr__(self, key, value):
ident = get_ident()
if ident in self.DIC:
self.DIC[ident][key] = value
else:
self.DIC[ident] = {key:value}
obj = Local()
def task(i):
obj.test = i
time.sleep(2)
print(obj.test,i)
for i in range(10):
t = threading.Thread(target=task,args=(i,))
t.start()
- 应用
- Flask上下文管理中的Local类更高级
- DBUtils线程池的模式一:为每个线程创建一个连接。
- SQLAlchemy
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session
from models import Student,Course,Student2Course
engine = create_engine(
"mysql+pymysql://root:[email protected]:3306/s9day120?charset=utf8",
max_overflow=0, # 超过连接池大小外最多创建的连接
pool_size=5, # 连接池大小
pool_timeout=30, # 池中没有线程最多等待的时间,否则报错
pool_recycle=-1 # 多久之后对线程池中的线程进行一次连接的回收(重置)
)
SessionFactory = sessionmaker(bind=engine)
# 为每个线程创建一个连接
session = scoped_session(SessionFactory)
def task():
ret = session.query(Student).all()
# 将连接交还给连接池
session.remove()
from threading import Thread
for i in range(20):
t = Thread(target=task)
t.start()
5. 上下文管理
请求到来时候:
# ctx = RequestContext(self, environ) # self是app对象,environ请求相关的原始数据
# ctx.request = Request(environ)
# ctx.session = None
# 将包含了request/session的ctx对象放到“空调”
{
1232:{ctx:ctx对象}
1231:{ctx:ctx对象}
1211:{ctx:ctx对象}
1111:{ctx:ctx对象}
1261:{ctx:ctx对象}
}
视图函数:
from flask import reuqest,session
request.method
请求结束:
根据当前线程的唯一标记,将“字典”上的数据移除。