赞
踩
# @app.route('/index')干了什么事?
1、先执行 app.route('/index'),返回值decorator
2、再执行:@decorator
3、把它装饰的函数当作参数传递到源码执行:decorator(func)
4、decorator源码如下:
def route(self, rule, **options):
def decorator(f):
endpoint = options.pop("endpoint", None)
# rule='路由'
# endpoint=别名,如果不传就是函数名,不能多个路由的重名
# f=函数
self.add_url_rule(rule, endpoint, f, **options)
return f
return decorator
# 方式一(主流方式)
@app.route('/index')
def index():
return 'index'
# 方式二
def index():
return 'index'
app.add_url_rule('/index', None, index) # (路由,别名,函数)
# app.route()的参数
rule:url
view_func:视图函数名称
defaults:给函数传递一个默认值
endpoint:反向解析起别名,即url_for('别名')
strict_slashes:这个写成False之后,路由对后面的/就不再严格要求
redirect_to:如果系统更新,可以把旧地址重定向到新地址,确保正常访问
subdomain:子域名访问
from flask import views, Flask from functools import wraps app = Flask(__name__) def wrapper(func): @wraps(func) def inner(*args, **kwargs): return func(*args, **kwargs) return inner class UserView(views.MethodView): # 先执行:self.dispatch_request,再决定执行哪个请求函数 methods = ['GET', 'POST'] # 指定允许的请求方式 decorators = [wrapper, ] # 装饰器在请求方式执行之前执行,比如before_request装饰的功能 def get(self, *args, **kwargs): return 'GET' def post(self, *args, **kwargs): return 'POST' # 路由不能再用装饰器了,而要采取如下方式 app.add_url_rule('/user', None, UserView.as_view('endpoint')) if __name__ == '__main__': app.run()
# https://www.cnblogs.com/wupeiqi/articles/7552008.html from flask import Flask, views, url_for from werkzeug.routing import BaseConverter app = Flask(import_name=__name__) # 第一步:定制类 class RegexConverter(BaseConverter): """ 自定义URL匹配正则表达式 """ def __init__(self, map, regex): super(RegexConverter, self).__init__(map) self.regex = regex def to_python(self, value): """ 路由匹配时,匹配成功后传递给视图函数中参数的值 """ return int(value) # 此处可做类型转换 def to_url(self, value): """ 使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成URL中的参数 """ val = super(RegexConverter, self).to_url(value) return val # 第二步:添加到转换器中 app.url_map.converters['regex'] = RegexConverter """ 1、用户发送请求 2、flask内部进行正则匹配 3、调用to_python(正则匹配的结果)方法 4、to_python方法的返回值会交给视图函数的参数 """ # 第三步:使用自定义正则 @app.route('/index/<regex("\d+"):nid>') def index(nid): print(url_for('index', nid='888')) # 触发to_url()方法 return 'Index' if __name__ == '__main__': app.run()
from flask import Flask # 1、实例化Flask对象 app = Flask(import_name=__name__) # 2、设置路由 """ app.url_map=[('/index', index), ('/login', login)] """ @app.route('/index/') def index(): return 'Index' if __name__ == '__main__': # 3、启动socket服务器 app.run() # 4、用户请求来 # 执行app.__call__()
app.__call__()
def __call__(self, environ, start_response):
# environ:是请求相关的所有数据
# start_response:用于设置响应相关数据
return self.wsgi_app(environ, start_response)
self.wsgi_app(environ, start_response)
flask所有源码都是在这个函数里面触发的
def wsgi_app(self, environ, start_response): """ 1、获取environ并对其再次封装,得到request对象 2、从environ中获取名称为session的cookie,解密,反序列化 3、两个东西放到‘某个神奇’的地方:上下文管理 """ # ctx=RequestContext(self, environ) #self就是app对象 # ctx.request=Request(environ) # 可以request点出来了 # ctx.session=None ctx = self.request_context(environ) # 再次封装请求 error = None try: try: # 执行这句之前,ctx中已经封装了request和session了 # 将ctx放到‘某个神奇’的地方 # 执行SecureCookieSessionInterface.open_session,去cookie中获取值并给ctx.session重新赋值 ctx.push() # 调用session_interface # 4、执行视图函数 # 5、‘某个神奇’的地方获取session,加密,序列化,写入cookie response = self.full_dispatch_request() except Exception as e: error = e response = self.handle_exception(e) except: error = sys.exc_info()[1] raise return response(environ, start_response) finally: if self.should_ignore_error(error): error = None """ 6、‘某个神奇’的位置清空 """ ctx.auto_pop(error)
目标:给开发者提供目录结构
所有的视图都放在一个py文件中,管理非常不便。因此需要分目录管理。
pro_flask # 此目录要与项目名一致
statics
templates
views # 分项目写视图
- account.py
- blog.py
- user.py
__init__.py
run.py
run.py
:启动文件
from pro_flask import create_app
app = create_app()
if __name__ == '__main__':
app.run()
__init__.py
from flask import Flask # 导入蓝图 from .views.account import account from .views.blog import blog from .views.user import user def create_app() app = Flask(__name__,template_folder='templates',static_folder='statics',static_url_path='/static') # 可以全局装饰 @app.before_request def x1(): print('app.before_request') # 注册蓝图:给蓝图与app绑定关系 app.register_blueprint(account) app.register_blueprint(blog) app.register_blueprint(user, url_prefix='/api') # 加了url_prefix参数,后面访问时,在对应路由前面还要加这个前缀 return app
account.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')
其他两个视图与account.py
一样,只是蓝图的名字不同。
import threading
import time
v=0
def task(i):
global v
v=i # 多线程共同修改同一份数据,导致数据异常
time.sleep(1)
print(v) # 最后所有数据得到的都是9
for i in range(10):
t = threading.Thread(target=task, args=(i,))
t.start
要解决上面的问题,我们原来是要给数据修改的部分加锁,今天换一种方法
threading.local()
作用:
为每个线程创建一个独立的空间,使得线程对自己的空间中的数据进行操作(数据隔离),会浪费空间。
import threading
import time
v=0
obj = threading.local()
def task(i):
obj.xx = i
time.sleep(2) # 无论停几秒,结果都是一样的
print(obj.xx)
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]['xxx'] = i else: DIC[ident] = {'xxx': i} time.sleep(2) print(DIC[ident]['xxx'], 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 = greenlet.getcurrent() # 获取协程的唯一标记 if ident in DIC: DIC[ident]['xxx'] = i else: DIC[ident] = {'xxx': i} time.sleep(2) print(DIC[ident]['xxx'], i) # 打印数据与索引 for i in range(10): t = threading.Thread(target=task, args=(i,)) t.start
import threading try: import greenlet get_ident = greenlet.getcurrent except: get_ident = threading.get_ident class Local(object): DIC = {} # {'123':{'xx':123, 'x1': 4}} def __getattr__(self, item): # obj.xx的时候触发,xx要不存在 ident = get_ident() # 线程或协程 if ident in self.DIC: return self.DIC[ident].get(item) return None def __setattr__(self, key, value): # obj.xx=123触发 ident = get_ident() # 线程或协程 if ident in self.DIC: self.DIC[ident][key]=value else: self.DIC[ident]={key:value}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。