一、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. Gitlab简单使用指南

    原文链接 一.在gitlab的网站创建一个project 定一个项目名,选定相关的项目设置,private,public等 项目创建成功后,得到项目git@XXX.git的地址,可用于将project ...

  2. Vue--- mint-UI 穿插

    Vue-mint-UI库 概述:就是一个 封装好的库 安装/下载:npm install  --save mint-ui 常用 1) Mint UI:a. 主页: http://mint-ui.git ...

  3. 【BGP的基本配置】

    BGP的基本配置 一:根据项目需求搭建好拓扑图如下 二:配置 1:首先进行理论分析:RT1和RT2,3分别属于不同的AS;在RT1和RT2之间建立EBGP关系,在确保RT3可以学到RT1的8.1.1. ...

  4. linux总结及常用命令

    一.操作系统的作用: 1.是现代计算机系统中最基本和最重要的系统软件  2.承上启下的作用  3.向下对硬件操作进行封装  4.向上对用户和应用程序提供方便访问硬件的接口 二.不同领域的操作系统: 1 ...

  5. node、npm安装教程

    描述: Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境.Node.js 使用了一个事件驱动.非阻塞式 I/O 的模型,使其轻量又高效. Node.js 的使用包 ...

  6. Laravel-初步使用

    一.Laravel环境搭建 1.window环境下环境搭建请参考以下链接: 开发环境搭建 - Windows | <Laravel 开发环境部署> | PHP / Laravel 社区文档 ...

  7. JDK8新垃圾回收机制--G1垃圾回收机制

    G1全称是Garbage First Garbage Collector,使用G1的目的是简化性能优化的复杂性.例如,G1的主要输入参数是初始化和最大Java堆大小.最大GC中断时间. G1 GC由Y ...

  8. python3 练习题100例 (二十二)输入两个字符串,输出两个字符串集合的并集

    题目内容: 输入两个字符串,输出两个字符串集合的并集. 为保证输出结果一致,请将集合内元素排序之后再输出, 如对于集合aset,可输出sorted(aset). 输入格式: 共两行,每一行为一个字符串 ...

  9. 让CPU使用率正弦变化

    网络上流传一个面试题,说如何编程让CPU的使用率按照正弦方式变化 代码如下(运行环境Linux): #include <stdio.h> #include <stdlib.h> ...

  10. go学习笔记-语言指针

    语言指针 定义及使用 变量是一种使用方便的占位符,用于引用计算机内存地址.取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址. 一个指针变量指向了一个值的内存地址.类似于变量和常量, ...