配置文件
路由系统
视图
请求相关
响应
模板渲染
session
闪现
中间件
蓝图(blueprint)
给你一个路径 “settings.Foo”,可以找到类并获取其中的大写的静态字段。
settings.py
1 2 3 |
|
xx.py
1 2 3 4 5 6 7 8 9 10 11 12 |
|
importlib模块
实现机制:根据字符串的形式导入模块,通过反射找到里面的内容,有一个特点,只有全部大写才能被读到。
导入方式:app.config.from_object()
默认配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
|
修改配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
|
常用:app.config.from_object()
本质:带参数的装饰器和闭包实现的。
@app.route('/user/
@app.route('/post/
@app.route('/post/
@app.route('/post/
@app.route('/login', methods=['GET', 'POST'])
常用路由系统有以上五种,所有的路由系统都是基于一下对应关系来处理:
1 2 3 4 5 6 7 8 9 |
|
总结:
1 2 3 4 |
|
FBV
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
1 2 3 4 5 |
|
注:jsonify内部帮我们序列化,跟django的jsonresponse有点相似。
我们返回的都是响应体,页面可以看到的。那我们如何加响应头?
如果我们想要返回相关的信息时,可以通过make_response将我们的内容封装起来。
1 2 3 4 |
|
那我们可以设置cookie吗?
1 2 3 4 5 6 |
|
Flask使用的是Jinja2模板,所以其语法和Django无差别
Flask中自定义模板方法的方式和Bottle相似,创建一个函数并通过参数的形式传入render_template,如:
自定义函数
{{ww()|safe}}
#!/usr/bin/env python # -*- coding:utf-8 -*- from flask import Flask,render_template app = Flask(__name__) def wupeiqi(): return 'yaya
' @app.route('/login', methods=['GET', 'POST']) def login(): return render_template('login.html', ww=yaya) app.run()
Title {% macro input(name, type='text', value='') %} {% endmacro %} {{ input('n1') }} {% include 'tp.html' %}asdf{{ v.k1}}
注意:Markup等价django的mark_safe
基本数据类型
可以执行python语法,如:dict.get(),list["xx"]
传入函数
Django中函数自动加括号执行;
Flask中不自动执行,需要自己主动执行,可以传参数。
全局定义函数
1 2 3 4 5 6 7 8 9 |
|
模板继承
layout.html
1 2 3 4 5 6 7 8 9 10 11 12 |
|
tpl.html
1 2 3 4 5 6 7 |
|
include
1 2 3 4 5 6 7 8 |
|
宏
1 2 3 4 5 |
|
#默认不显示,相当于定义了函数没执行,想要执行,需要调用
要用几次,就调用几遍
1 2 3 |
|
安全
前端做法
1 |
|
后端做法
1 |
|
注:Flask中的markup相当于Django中的mark_safe.
除请求对象之外,还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名要使用会话,你需要设置一个密钥。
设置:session['username'] = 'xxx'
from flask import Flask, session, redirect, url_for, escape, request app = Flask(__name__) @app.route('/') def index(): if 'username' in session: return 'Logged in as %s' % escape(session['username']) return 'You are not logged in' @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'POST': session['username'] = request.form['username'] return redirect(url_for('index')) return '''''' @app.route('/logout') def logout(): # remove the username from the session if it's there session.pop('username', None) return redirect(url_for('index')) # set the secret key. keep this really secret: app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
pip3 install Flask-Session run.py from flask import Flask from flask import session from pro_flask.utils.session import MySessionInterface app = Flask(__name__) app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT' app.session_interface = MySessionInterface() @app.route('/login.html', methods=['GET', "POST"]) def login(): print(session) session['user1'] = 'alex' session['user2'] = 'alex' del session['user2'] return "内容" if __name__ == '__main__': app.run() session.py #!/usr/bin/env python # -*- coding:utf-8 -*- import uuid import json from flask.sessions import SessionInterface from flask.sessions import SessionMixin from itsdangerous import Signer, BadSignature, want_bytes class MySession(dict, SessionMixin): def __init__(self, initial=None, sid=None): self.sid = sid self.initial = initial super(MySession, self).__init__(initial or ()) def __setitem__(self, key, value): super(MySession, self).__setitem__(key, value) def __getitem__(self, item): return super(MySession, self).__getitem__(item) def __delitem__(self, key): super(MySession, self).__delitem__(key) class MySessionInterface(SessionInterface): session_class = MySession container = {} def __init__(self): import redis self.redis = redis.Redis() def _generate_sid(self): return str(uuid.uuid4()) def _get_signer(self, app): if not app.secret_key: return None return Signer(app.secret_key, salt='flask-session', key_derivation='hmac') def open_session(self, app, request): """ 程序刚启动时执行,需要返回一个session对象 """ sid = request.cookies.get(app.session_cookie_name) if not sid: sid = self._generate_sid() return self.session_class(sid=sid) signer = self._get_signer(app) try: sid_as_bytes = signer.unsign(sid) sid = sid_as_bytes.decode() except BadSignature: sid = self._generate_sid() return self.session_class(sid=sid) # session保存在redis中 # val = self.redis.get(sid) # session保存在内存中 val = self.container.get(sid) if val is not None: try: data = json.loads(val) return self.session_class(data, sid=sid) except: return self.session_class(sid=sid) return self.session_class(sid=sid) def save_session(self, app, session, response): """ 程序结束前执行,可以保存session中所有的值 如: 保存到resit 写入到用户cookie """ domain = self.get_cookie_domain(app) path = self.get_cookie_path(app) httponly = self.get_cookie_httponly(app) secure = self.get_cookie_secure(app) expires = self.get_expiration_time(app, session) val = json.dumps(dict(session)) # session保存在redis中 # self.redis.setex(name=session.sid, value=val, time=app.permanent_session_lifetime) # session保存在内存中 self.container.setdefault(session.sid, val) session_id = self._get_signer(app).sign(want_bytes(session.sid)) response.set_cookie(app.session_cookie_name, session_id, expires=expires, httponly=httponly, domain=domain, path=path, secure=secure)
#!/usr/bin/env python # -*- coding:utf-8 -*- """ pip3 install redis pip3 install flask-session """ from flask import Flask, session, redirect from flask.ext.session import Session app = Flask(__name__) app.debug = True app.secret_key = 'asdfasdfasd' app.config['SESSION_TYPE'] = 'redis' from redis import Redis app.config['SESSION_REDIS'] = Redis(host='192.168.0.94',port='6379') Session(app) @app.route('/login') def login(): session['username'] = 'alex' return redirect('/index') @app.route('/index') def index(): name = session['username'] return name if __name__ == '__main__': app.run()
以加密的形式放到浏览器的cookie里面。
用户浏览器可以禁用cookie,禁用掉之后就不能用。用户登录就不能成功。
请求进来去cookie中把数据拿到,拿到之后将数据解密并反序列化成字典放到内存,让视图函数使用,视图函数使用完交给其他人,再进行序列化加密放到session中去,
本质:放到session,再给他移除掉。
当请求刚到来:flask读取cookie中session对应的值:eyJrMiI6NDU2LCJ1c2VyIjoib2xkYm95,将该值解密并反序列化成字典,放入内存以便视图函数使用。
视图函数:
1 2 3 4 5 6 7 |
|
session是以字典的形式保存在cookie中,字典有啥操作,它就有啥操作。
当请求结束时,flask会读取内存中字典的值,进行序列化+加密,写入到用户cookie中。
可以在配置文件中对相应的配置进行修改。
生命周期默认是31天,可以修改。Django中cookie生命周期默认是2周。
是一个基于Session实现的用于保存数据的集合,其特点是:使用一次就删除。
在session中存储一个数据,读取时通过pop将数据移除。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
请求执行wsgi.app之前和之后定制一些操作,用的是call方法。
Django和Falsk请求源码的入口就是call方法。
call方法什么时候触发?
用户发起请求时,才执行。
任务
在执行call方法之前,做一个操作,call方法执行之后做一个操作。
方式一:改源码
方式二:
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Django中的中间件是请求和响应时做一些操作,而Flask中间件是自定义一些操作。在请求执行之前和执行之后定制一些操作。
Flask源码入口:
目标
给开发者提供目录结构
简单蓝图步骤:
总结:
其他
1、如果某一个蓝图想在别的地方找模板,怎么办?
如上所示,在实例化蓝图中可以自定义模板位置。那蓝图如果想用模板怎么找?
先找目录下的template下的,没有才去蓝图中找。跟Django一样。(先在项目中找,没找到再去app中去找。)
2、还可以给某一类加前缀。
在每次执行前都要加上前缀,否则报错。
3、可以给某一类添加before_request
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
这个什么时候用到呢?
登录认证。
只要登录成功才能访问的蓝图中就加before_request.
before_request
after_request
flask与django1.9版本之前,不管请求函数有没有return,中间件响应函数都执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
|
before_first_request
项目启动起来,第一次请求才执行。
是一个标识,最开始是True,第一次请求之后改为False,就不再执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
template_global
给模板用
1 2 3 4 |
|
template_filter
给模板用
1 2 3 4 |
|
errorhandler
定制错误页面
1 2 3 4 |
|