Flask 学习笔记(一)
一、Web 服务器与 Web 框架
首先明确一下,要运行一个动态网页,我们需要
- 一个 Web 服务器来监听并响应请求,如果请求的是静态文件它就直接将其返回,如果是动态 url 它就将请求转交给 Web 应用。
- 一个 Web 应用来动态处理请求,生成响应
其中 Web 服务器通常都是别人已经实现好了的,它通过定义好的接口与我们编写的 Web 应用通信。WSGI 就是一个统一的 Web 服务器接口标准,如果我们按照 WSGI 编写 Web 应用,那么它就能在任何符合该标准的服务器上运行,例如 Gunicorn.(对比一下 Java 的 Servlet,按照 Servlet 规范编写的应用,都能运行在任何 Servlet 容器上,例如 Tomcat 和 Jetty,Servlet 容器就相当于 WSGI 服务器)
可是 WSGI 仍然比较底层,直接照着它写太麻烦,于是就有了 Web 框架,Python 知名的就是 Flask 和 Django。Java 的 Servlet 也是如此,对应的出现了 Spring MVC 框架。但是 Flask 和 Django 都有内置服务器用于测试,而 Spring MVC 没有,倒是 Spring Boot 可以使用内嵌的 tomcat 容器。
二、Flask
Flask 是一个微框架,“微”是指它的核心非常小,任何可选的功能都不包括在内。但是 Flask 社区提供了丰富的拓展插件,你可以通过选择需要的插件来实现你想要的功能。
中间略过 n 万字。。。
三、上下文 Context
上下文 Context,是动态创建的东西。flask 通过四个全局代理对象,提供对上下文的访问:
- current_app 和 g:应用上下文
- request 和 session:请求上下文
1. 请求上下文 Request Context
Java 的 Spring MVC 将请求作为方法参数传入,而且要求参数必须映射到某个类型或者某个 model 上。
Flask 的处理方式与之不同,它提供了一个全局代理对象——request,只要是在请求从开始到结束的过程中,都可以直接通过这个 request 访问 HTTP 请求的各种参数。
请求上下文在请求开始时被压入栈,这时 request 对象才可用,在请求结束后会立即被 pop 出来。
疑问
为什么 request 得是一个代理对象呢?
- 在视图函数被 load 时,很可能连 app 都还没有创建(如果用工厂模式 create_app 的话),更不可能存在 request 了。
- 因此 request 只能是一个占位符(代理对象),等到请求真正到来时,flask 再将请求数据 push 到 request_stack 内,这时 request 对象就可用了。
2. 应用上下文 Application Context
一个 app,就是一个 Flask 实例,通过 app = Flask(__name__)
创建。
在请求到来时,除了请求上下文被入栈,还有应用上下文也会被入栈。
请求结束时,它先 pop 出请求上下文,然后是应用上下文。
也就是说在请求过程中,应用上下文是可用的,current_app 就是当前 app 实例的代理,对它进行任何操作,都会直接影响到 app 本身!!(current_app 的修改是全局的!)
疑问
在 flask 初始化时,我们不是已经通过 app = Flask(__name__)
创建了一个 app 实例了么?直接用它不行么?
- 在工厂模式下,
app = Flask(__name__)
会在create_app()
被调用时,才会执行。- 可是在这之前,整个 Web 项目就会被初始化。初始化时根本不存在 app 实例。因此只能先用个 current_app 做占位符(代理对象)
- 编写可重用的 blueprint 时,你不知道要从哪里导入 app 实例。如果直接用 current_app,就不需要去管 app 什么时候在哪被创建了。
3. g 对象(应用上下文)
g 对象,名称来源于 global
,保存在应用上下文中,指应用上下文中的全局变量。(其实每个请求都拥有独立的 g 对象)
如果我们需要在当前请求中传递数据(请求结束,数据就销毁),是不能使用 current_app 的,因为对 current_app 的操作会直接影响到 app 本身。
但是应用上下文本身的生命周期,是和请求上下文相同的,flask 在应用上下文中提供了 g 对象,该对象不是什么别的代理!!因此对它的操作,在请求结束时,就会连同 current_app 一起被销毁。
4. session 对象(请求上下文)
session 位于 请求上下文中。它的内容会被保存到 cookie 中,发送到客户端。每次收到请求时又会从 cookie 中加载它。因此它可用于跨请求传输数据。
这种 session 被称为客户端 session(client side session)
session 被存入 cookie 前,会使用你设定的 SECRET_KEY
签名,这样才能确认请求中的 session 就是 flask 发送出去的,没有被人修改过,或者说不是伪造的。(除非你的 SECRET_KEY
泄漏了。。)
但是签名不是数据加密,session 的内容很容易被解码出来,因此 session 只适合存放非敏感数据!!!下面是 session 解密代码:
#!/usr/bin/env python3
import sys
import zlib
from base64 import b64decode
from flask.sessions import session_json_serializer
from itsdangerous import base64_decode
def decryption(payload):
payload, sig = payload.rsplit(b'.', 1)
payload, timestamp = payload.rsplit(b'.', 1)
decompress = False
if payload.startswith(b'.'):
payload = payload[1:]
decompress = True
try:
payload = base64_decode(payload)
except Exception as e:
raise Exception('Could not base64 decode the payload because of '
'an exception')
if decompress:
try:
payload = zlib.decompress(payload)
except Exception as e:
raise Exception('Could not zlib decompress the payload before '
'decoding the payload')
return session_json_serializer.loads(payload)
if __name__ == '__main__':
print(decryption(sys.argv[1].encode()))
通过命令行传入你的 session,它就能直接给出内容!
如果你确实需要在 session 中存放敏感数据(比如验证码),那么你可以阅读一下参考链接中的文章
四、插件
- python-dotenv:配置文件
- flask_wtform:表单
- flask-login:登录与权限验证
- flask-sqlalchemy + flask-migrate:数据库
- flask-rest-api:restful api
- flask-Sockets:websocket
- flask-mail: 邮件发送
- flask-limiter: ip 访问频率限制(防爬)
- flask-security: 整合了 flask-login flask-mail 等一系列用户验证相关的插件,提供完善的权限验证功能。
- flask-admin: 可以很方便的构建网站管理后台
- flask-caching: 缓存
四、使用 blueprint(蓝图)
入门级 flask app 都是单文件应用,当复杂度上升,我们可以把单文件应用分成多个文件,比如:views.py、models.py、forms.py、errors.py。
但是如果项目继续增大,各个文件也会渐渐变得难以维护。views.py 中各种功能的视图函数混在一起,models.py 和 forms.py 也是。显然我们可以按功能,继续分割这几个代码文件。
blueprint 就是用于应对大型项目开发的功能,使用它可以对上述的文件按功能做进一步的拆分。
蓝图使用起来就像应用当中的子应用一样,可以有自己的模板,静态目录,有自己的视图函数和URL规则,蓝图之间互相不影响。但是它们又属于应用中,可以共享应用的配置。
实际上 BluePrint 类的使用也几乎和 Flask 一模一样。差别只是 BluePrint 最后还需要在 Flask 实例中注册:app.register_blueprint(<blue_print_obj>)
.
注意事项
- url_for 的第一个参数 endpoint,是 view function 的名称,不是 route 路径!
- 使用 blueprint 时,endpoint 为
蓝图名称.视图函数名称
- 使用 blueprint 时,endpoint 为
- 读取资源文件:资源文件可以放在
data
文件夹下,使用flask.open_resources("data/<file_name>", mode="rb")
读取资源文件。- 不放在
static
下的原因是,该目录内的文件是可以直接通过 URI/static/<file_path>
访问的,是公开的。我们一般不希望用户直接访问这种资源文件。
- 不放在
- flask 的内置服务器和 gunicorn 都不支持 http2、keep-alive(http1.1),也没有 gzip 实体压缩。这些功能通常都通过使用 nginx 做反向代理来获得。
- gunicorn 对此的解释是,gunicorn 就是设计用来放在 nginx 后面运行的,而 nginx 与它的 upstream 通信时默认使用 http1.0
链接
- flask
- the-flask-mega-tutorial
- flask的上下文疑问 current_app, g, session, request?
- Flask的g对象,范围是什么?
- Modular Applications with Blueprints
- 客户端 session 导致的安全问题
- How Secure Is The Flask User Session?
Flask 学习笔记(一)的更多相关文章
- Python Flask学习笔记之模板
Python Flask学习笔记之模板 Jinja2模板引擎 默认情况下,Flask在程序文件夹中的templates子文件夹中寻找模板.Flask提供的render_template函数把Jinja ...
- Python Flask学习笔记之Hello World
Python Flask学习笔记之Hello World 安装virtualenv,配置Flask开发环境 virtualenv 虚拟环境是Python解释器的一个私有副本,在这个环境中可以安装私有包 ...
- Flask 学习笔记
Flask 是一个Web应用框架,我也就是一边看书,一边写博文做记录 这本书: 首先安装Flask ,和配置环境,参考这边博客: 然后就开始学习Flask 了. 1.Application and R ...
- Flask 学习笔记(二):RESTful API
概括 URL:需要操作的对象,也就是资源 HTTP method:我要对该对象做什么(POST 增.DELETE 删.GET 查.PUT 和 PATCH 改) HTTP status code:操作的 ...
- 【Flask】Flask学习笔记(一) 应用基本结构
初始化 使用前必须创建一个应用实例 from flask import Flask app = Flask(__name__) 路由和视图函数 请求流程 客户端(web浏览器)--> web服 ...
- flask学习笔记(1)-虚拟环境安装
Mac(类Linux): pip install virtualenv mkdir testvirtualenv cd testvirtualenv virtualenv flask-env#创建虚拟 ...
- Flask学习笔记(3)--路由
0x01 参数传递 传递参数的语法是: /<参数名>/,然后在视图函数中,也要定义同名的参数. 参数的数据类型: 1.如果没有指定具体的数据类型,那么默认就是使用string 数据类型. ...
- Flask学习笔记(2)--最简单的小应用
0x01 第一个小程序 PyCharm新建一个flask项目,第一个小程序,我们来看一下 #引入flask类 from flask import Flask #将Flask对象实例化 app = Fl ...
- Flask 学习笔记(1)--环境安装
Flask 官网:http://flask.pocoo.org/ Flask文档:http://docs.jinkan.org/docs/flask/ 0x01 安装方式 安装步骤很简单,就是这个样子 ...
- pythonweb框架Flask学习笔记05-简单登陆
源代码从下链接引用:https://www.cnblogs.com/felixwang2/p/9261493.html 我使用的是python3.6 在运行代码的时候遇到了以下问题 session[' ...
随机推荐
- property--name--id-这三者在值传递的过程中的实现关系
作者:light链接:https://www.zhihu.com/question/286739416/answer/454300180来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转 ...
- LeetCode 中级 - 有序链表转换二叉搜索树(109)
给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1. 示例: 给定的有序链表: [-10 ...
- ABAP术语-Business Framework Architecture
Business Framework Architecture 原文:http://www.cnblogs.com/qiangsheng/archive/2007/12/29/1019277.html ...
- ubuntu部署kubeadm1.13.1高可用
kubeadm的主要特性已经GA了,网上看很多人说1.13有bug在1.13.1进行的更新,具体我也没怎么看,有兴趣的朋友可以查查,不过既然有人提到了我们就不要再去踩雷了,就用现在的1.13.1来部署 ...
- (转)Dubbo 简单Dome搭建
(转)原地址https://blog.csdn.net/noaman_wgs/article/details/70214612/ Dubbo背景和简介 Dubbo开始于电商系统,因此在这里先从电商系统 ...
- Windows之cmd指令
gpedit.msc-----本地计算机策略sndrec32-------录音机 Nslookup-------IP地址侦测器 explorer-------打开资源管理器 logoff------- ...
- Node.js中的不安全跳转如何防御详解
Node.js中的不安全跳转如何防御详解 导语: 早年在浏览器大战期间,有远见的Chrome认为要运行现代Web应用,浏览器必须有一个性能非常强劲的Java引擎,于是Google自己开发了一个高性能的 ...
- 通过SVI实现VLAN间通信
两个不同网段的计算机与三层交换机直连,通过SVI实现VLAN间通信vlan 1 //几个不同网段就创建几个VLANvlan 2 int f0/1 //划分VLANswitchport mode acc ...
- idea启动spring boot无法加载或找不到主类
问题产生原因:moudle名称修改,导致项目启动不了 在Terminal界面中执行以下三个命令,我在执行第一个命令的时候报了一个找不到dependency的错误,把那个报错的dependency删了就 ...
- Spark Streaming实时处理应用
1 框架一览 事件处理的架构图如下所示. 2 优化总结 当我们第一次部署整个方案时,kafka和flume组件都执行得非常好,但是spark streaming应用需要花费4-8分钟来处理单个 ...