Flask框架二
Flask配置文件
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()
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()
上下文管理
上下文管理(第一次) 请求到来时候: # 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实现用户登录
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。。 有一种默契叫做我不理你,你就不理我

浙公网安备 33010602011771号