Flask框架二
Flask配置文件
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为: { 'DEBUG': get_debug_flag(default=False), 是否开启Debug模式 'TESTING': False, 是否开启测试模式 'PROPAGATE_EXCEPTIONS': None, 'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'SECRET_KEY': None, 'PERMANENT_SESSION_LIFETIME': timedelta(days=31), 'USE_X_SENDFILE': False, 'LOGGER_NAME': None, 'LOGGER_HANDLER_POLICY': 'always', 'SERVER_NAME': None, 'APPLICATION_ROOT': None, 'SESSION_COOKIE_NAME': 'session', 'SESSION_COOKIE_DOMAIN': None, 'SESSION_COOKIE_PATH': None, 'SESSION_COOKIE_HTTPONLY': True, 'SESSION_COOKIE_SECURE': False, 'SESSION_REFRESH_EACH_REQUEST': True, 'MAX_CONTENT_LENGTH': None, 'SEND_FILE_MAX_AGE_DEFAULT': timedelta(hours=12), 'TRAP_BAD_REQUEST_ERRORS': False, 'TRAP_HTTP_EXCEPTIONS': False, 'EXPLAIN_TEMPLATE_LOADING': False, 'PREFERRED_URL_SCHEME': 'http', 'JSON_AS_ASCII': True, 'JSON_SORT_KEYS': True, 'JSONIFY_PRETTYPRINT_REGULAR': True, 'JSONIFY_MIMETYPE': 'application/json', 'TEMPLATES_AUTO_RELOAD': None, }
Session
当请求刚到来时,flask读取cookie中session对应的值,将加密的值解密反序列化成字典,放到视图函数。
当请求结束,flask会读取内存中session的值并放到浏览器的cookie中
除请求对象之外,还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名要使用会话,你需要设置一个密钥。
-
设置:session['username'] = 'xxx'
- 删除:session.pop('username', None)
闪现Flash
from flask import Flask,flash,get_flashed_messages @app.route('/page1') def page1(): flash('临时数据存储','error') flash('sdfsdf234234','error') flash('adasdfasdf','info') return "Session" @app.route('/page2') def page2(): print(get_flashed_messages(category_filter=['error'])) 根据分类取数据 return "Session"
只存在于相邻请求之间,第一次请求赋值,第二期请求获取值,第三次闪现内容不会出现
中间件
call方法什么时候出发? - 用户发起请求时,才执行。 任务:在执行call方法之前,做一个操作,call方法执行之后做一个操作。 class Middleware(object): def __init__(self,old): self.old = old def __call__(self, *args, **kwargs): ret = self.old(*args, **kwargs) return ret if __name__ == '__main__': app.wsgi_app = Middleware(app.wsgi_app) app.run()
from flask import Flask app = Flask(__name__) @app.route('/') def index(): return 'Hello World!' class Md(object): def __init__(self,old_wsgi_app): self.old_wsgi_app = old_wsgi_app def __call__(self, environ, start_response): print('开始之前') # 。。。一些自定义操作 ret = self.old_wsgi_app(environ, start_response) # 。。。一些自定义操作 print('结束之后') return ret if __name__ == '__main__': # 封装旧的app.wsgi_app,这是app.run()的原理,看源码。会调用__call__方法 app.wsgi_app = Md(app.wsgi_app) app.run()
flask中间件,在请求之前和之后分别进行操作
特殊装饰器
@before_request (自上而下)
before_request中如果有返回值,那么页面上将会返回before_request返回值,不在往下执行before_request和视图函数,倒序执行after_request
#在执行视图函数之前,requset都要经过(before_request)
@app.before_first_request
@after_request(response) (自下往上执行)
@template_global
见模板
@template_filter
见模板
@errorhandler
出现错误时,自定制返回的内容
@app.errorhandler(404) def not_found(arg): #arg 错误信息 print(arg) return "没找到"
蓝图给开发者提供目录结构
1.创建与项目名相同的文件夹
2.在该文件下创建__init__.py
3.在与文件同一级的目录下创建manage.py
4.创建该项目的静态文件和模板
.蓝图的关系的创建
manage.py中
from crm import create_app app = create_app() if __name__ == '__main__': app.run()
__init__.py
from flask import Flask from .views.account import ac from .views.user import uc def create_app(): app = Flask(__name__) # @app.before_request # def x1(): # print('app.before_request') app.register_blueprint(ac) app.register_blueprint(uc,url_prefix='/api') return app
account.py
from flask import Blueprint,render_template ac = Blueprint('ac',__name__) @ac.before_request def x1(): print('app.before_request') @ac.route('/login') def login(): return render_template('login.html') @ac.route('/logout') def logout(): return 'Logout'
user.py
from flask import Blueprint uc = Blueprint('uc',__name__) @uc.route('/list') def list(): return 'List' @uc.route('/detail') def detail(): return 'detail'
- 在__init__.py 里面加上@before_request 方法把所有的请求都会经过
- 在每一个蓝图加上@before_request 那么就意味着只有该蓝驱的所有请求经过
threading.local
为每一个线程开辟独立空间
获取一个线程的唯一标识, threading.get_ident()
获取携程的唯一标识,greenlet.getcurrent()
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
threading.local【和flask无任何关系】 作用:为每个线程创建一个独立的空间,使得线程对自己的空间中的数据进行操作(数据隔离)。 import threading from threading import local import time obj = local() def task(i): obj.xxxxx = i time.sleep(2) print(obj.xxxxx,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]['xxxxx'] = i else: DIC[ident] = {'xxxxx':i } time.sleep(2) print(DIC[ident]['xxxxx'],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]['xxxxx'] = i else: DIC[ident] = {'xxxxx':i } time.sleep(2) print(DIC[ident]['xxxxx'],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.xxxxx = i time.sleep(2) print(obj.xxxxx,i) for i in range(10): t = threading.Thread(target=task,args=(i,)) t.start()
上下文管理
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
上下文管理(第一次) 请求到来时候: # 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 请求结束: 根据当前线程的唯一标记,将“空调”上的数据移除。
Session+Flask实现用户登录
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from flask import Flask,render_template,request,session,redirect app=Flask(__name__) #session 如果需要用到session 需要加盐. # 本质上他是放在cookies里,并不是像django一样放在数据库 app.secret_key ='213fdasfa123df' @app.route('/login',methods=['GET','POST']) def Login(): if request.method =='GET': return render_template('login.html') user=request.form.get('user') pwd=request.form.get('pwd') if user=='ming' and pwd=='123': session['user_info']={'username':user} return redirect('/index') return render_template('login.html',error='用户名或密码错误') # return render_template('login.html',**{'error':'用户名或者密码错误'}) @app.route('/index') def index(): user_info=session.get('user_info') if user_info: return render_template('index.html') return redirect('/login') if __name__ == '__main__': app.run()
I can feel you forgetting me。。 有一种默契叫做我不理你,你就不理我