一、Web 服务器与 Web 框架

首先明确一下,要运行一个动态网页,我们需要

  1. 一个 Web 服务器来监听并响应请求,如果请求的是静态文件它就直接将其返回,如果是动态 url 它就将请求转交给 Web 应用。
  2. 一个 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 通过四个全局代理对象,提供对上下文的访问:

  1. current_app 和 g:应用上下文
  2. 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 实例了么?直接用它不行么?

  1. 在工厂模式下,app = Flask(__name__) 会在 create_app() 被调用时,才会执行。

    • 可是在这之前,整个 Web 项目就会被初始化。初始化时根本不存在 app 实例。因此只能先用个 current_app 做占位符(代理对象)
  2. 编写可重用的 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 中存放敏感数据(比如验证码),那么你可以阅读一下参考链接中的文章

四、插件

  1. python-dotenv:配置文件
  2. flask_wtform:表单
  3. flask-login:登录与权限验证
  4. flask-sqlalchemy + flask-migrate:数据库
  5. flask-rest-api:restful api
  6. flask-Sockets:websocket
  7. flask-mail: 邮件发送
  8. flask-limiter: ip 访问频率限制(防爬)
  9. flask-security: 整合了 flask-login flask-mail 等一系列用户验证相关的插件,提供完善的权限验证功能。
  10. flask-admin: 可以很方便的构建网站管理后台
  11. 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>).

注意事项

  1. url_for 的第一个参数 endpoint,是 view function 的名称,不是 route 路径!

    • 使用 blueprint 时,endpoint 为 蓝图名称.视图函数名称
  2. 读取资源文件:资源文件可以放在 data 文件夹下,使用 flask.open_resources("data/<file_name>", mode="rb") 读取资源文件。
    • 不放在 static 下的原因是,该目录内的文件是可以直接通过 URI /static/<file_path> 访问的,是公开的。我们一般不希望用户直接访问这种资源文件。
  3. flask 的内置服务器和 gunicorn 都不支持 http2、keep-alive(http1.1),也没有 gzip 实体压缩。这些功能通常都通过使用 nginx 做反向代理来获得。
    • gunicorn 对此的解释是,gunicorn 就是设计用来放在 nginx 后面运行的,而 nginx 与它的 upstream 通信时默认使用 http1.0

链接

Flask 学习笔记(一)的更多相关文章

  1. Python Flask学习笔记之模板

    Python Flask学习笔记之模板 Jinja2模板引擎 默认情况下,Flask在程序文件夹中的templates子文件夹中寻找模板.Flask提供的render_template函数把Jinja ...

  2. Python Flask学习笔记之Hello World

    Python Flask学习笔记之Hello World 安装virtualenv,配置Flask开发环境 virtualenv 虚拟环境是Python解释器的一个私有副本,在这个环境中可以安装私有包 ...

  3. Flask 学习笔记

    Flask 是一个Web应用框架,我也就是一边看书,一边写博文做记录 这本书: 首先安装Flask ,和配置环境,参考这边博客: 然后就开始学习Flask 了. 1.Application and R ...

  4. Flask 学习笔记(二):RESTful API

    概括 URL:需要操作的对象,也就是资源 HTTP method:我要对该对象做什么(POST 增.DELETE 删.GET 查.PUT 和 PATCH 改) HTTP status code:操作的 ...

  5. 【Flask】Flask学习笔记(一) 应用基本结构

    初始化 使用前必须创建一个应用实例 from flask import Flask app = Flask(__name__) 路由和视图函数 请求流程 客户端(web浏览器)-->  web服 ...

  6. flask学习笔记(1)-虚拟环境安装

    Mac(类Linux): pip install virtualenv mkdir testvirtualenv cd testvirtualenv virtualenv flask-env#创建虚拟 ...

  7. Flask学习笔记(3)--路由

    0x01 参数传递 传递参数的语法是: /<参数名>/,然后在视图函数中,也要定义同名的参数. 参数的数据类型: 1.如果没有指定具体的数据类型,那么默认就是使用string 数据类型. ...

  8. Flask学习笔记(2)--最简单的小应用

    0x01 第一个小程序 PyCharm新建一个flask项目,第一个小程序,我们来看一下 #引入flask类 from flask import Flask #将Flask对象实例化 app = Fl ...

  9. Flask 学习笔记(1)--环境安装

    Flask 官网:http://flask.pocoo.org/ Flask文档:http://docs.jinkan.org/docs/flask/ 0x01 安装方式 安装步骤很简单,就是这个样子 ...

  10. pythonweb框架Flask学习笔记05-简单登陆

    源代码从下链接引用:https://www.cnblogs.com/felixwang2/p/9261493.html 我使用的是python3.6 在运行代码的时候遇到了以下问题 session[' ...

随机推荐

  1. property--name--id-这三者在值传递的过程中的实现关系

    作者:light链接:https://www.zhihu.com/question/286739416/answer/454300180来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转 ...

  2. LeetCode 中级 - 有序链表转换二叉搜索树(109)

    给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1. 示例: 给定的有序链表: [-10 ...

  3. ABAP术语-Business Framework Architecture

    Business Framework Architecture 原文:http://www.cnblogs.com/qiangsheng/archive/2007/12/29/1019277.html ...

  4. ubuntu部署kubeadm1.13.1高可用

    kubeadm的主要特性已经GA了,网上看很多人说1.13有bug在1.13.1进行的更新,具体我也没怎么看,有兴趣的朋友可以查查,不过既然有人提到了我们就不要再去踩雷了,就用现在的1.13.1来部署 ...

  5. (转)Dubbo 简单Dome搭建

    (转)原地址https://blog.csdn.net/noaman_wgs/article/details/70214612/ Dubbo背景和简介 Dubbo开始于电商系统,因此在这里先从电商系统 ...

  6. Windows之cmd指令

    gpedit.msc-----本地计算机策略sndrec32-------录音机 Nslookup-------IP地址侦测器 explorer-------打开资源管理器 logoff------- ...

  7. Node.js中的不安全跳转如何防御详解

    Node.js中的不安全跳转如何防御详解 导语: 早年在浏览器大战期间,有远见的Chrome认为要运行现代Web应用,浏览器必须有一个性能非常强劲的Java引擎,于是Google自己开发了一个高性能的 ...

  8. 通过SVI实现VLAN间通信

    两个不同网段的计算机与三层交换机直连,通过SVI实现VLAN间通信vlan 1 //几个不同网段就创建几个VLANvlan 2 int f0/1 //划分VLANswitchport mode acc ...

  9. idea启动spring boot无法加载或找不到主类

    问题产生原因:moudle名称修改,导致项目启动不了 在Terminal界面中执行以下三个命令,我在执行第一个命令的时候报了一个找不到dependency的错误,把那个报错的dependency删了就 ...

  10. Spark Streaming实时处理应用

    1 框架一览   事件处理的架构图如下所示. 2 优化总结   当我们第一次部署整个方案时,kafka和flume组件都执行得非常好,但是spark streaming应用需要花费4-8分钟来处理单个 ...