第12章 Python Web 开发技术
12.1 通用网关接口(CGI)
12.1.1 CGI 的概念
- 直接基于Socket的Web应用的问题
- 要求熟悉HTTP协议和Socket编程
- 程序的可扩展性很差
- 难以支撑复杂的业务逻辑
- 通用网关接口(Common Gateway Interface,CGI)
- 是一种Web服务器和Web应用程序之间交互的编程规范,定义了Web服务器如何向Web应用程序发送消息,在收到Web应用程序的信息后如何处理等细节
- 遵循CGI规范的应用程序独立于Web服务器,并能够被Web服务器调用
- Web应用程序的开发者只需要关注业务逻辑代码的编写,无需关注HTTP协议或Socket等的底层细节
- 大大降低了Web应用程序的开发难度
- 通过标准输入输出进行通信,因而可以使用任意编程语言实现
- CGI编程的不足之处
- 在每一次HTTP请求中,Web服务器都需要执行CGI脚本,难以满足较大量并发请求的需要;
- CGI编程依旧比较复杂,相当多的交互依旧发生在HTTP协议的层面之上;
- CGI程序的安全性较差,容易受到攻击
12.1.2 Python CGI 编程
- Web应用程序目录
1 2 3 | |
- 服务器(两种方式)
- server.py
1 2 3 4 5 6 7 8 | |
python -m http.server --cgi 9000
- CGI脚本
- 必须具有可执行权限,在Linux系统中可使用命令
chmod a+x cgi.py添加执行权限; - 脚本中首注释中给出Python解释器的路径,例如
#!/usr/bin/python - first_cgi.py
1 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
在 CGI 脚本中获取请求参数
- 代码
- index.html中表单的
action属性改为/cgi-bin/post.py - post.py
1 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
使用Cookie
- cookie的发送
- 通过http头部来实现
Set-cookie:name=value;expires=date;path=path;domain=domain;securename=value:cookie变量的名称和取,有多个cookie变量时用;分隔,如name1=value1;name2=value2;expires=date:cookie的有效期限,date的格式为Wdy,DD-Mon-YYYY HH:MM:SS;path=path:cookie的支持路径,cookie对该路径中所有文件及子目录生效,例如path=/cgi-bin;domain=domain:cookie生效的域名,例如:domain="www.example.com";-
secure:表示cookie只能通过安全套接字协议(SSL)来传递。 -
cookie的接收
- 通过环境变量HTTP_COOKIE
1 | |
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 | |
12.2 Web 服务器网关接口(WSGI)
12.2.1 WSGI 的概念
- CGI编程的根本问题
- 每次请求都需要调用CGI脚本创建新的进程,并且响应完毕之后即抛弃
- 解决办法
- 第一种称为服务器集成,其思路是利用Web服务器提供的API开发Web应用,然后将Web应用作为模块插入到Web服务器中,Web服务器通过函数调用的方式来执行Web应用程序
- 要求Web应用与Web服务器使用相同的编程语言,而且Web服务器的稳定性直接受到Web应用程序的影响
- 第二种思路是外部进程,即令Web应用程序独立于Web服务器,形成独立的外部应用程序
- 需要制定新的专用于Web服务器和外部进程之间的通信协议,例如Java语言中的Servelet和Python语言中的WSGI(Web Server Gateway Interface)
12.2.2 WSGI 应用
- 满足如下条件的程序就是一个合法的WSGI应用
- 是一个可调用对象;
- 能够接收两个参数
- 第一个是包含了Web服务器环境变量的字典
- 第二个是一个用于设置HTTP响应状态码和响应头的函数
- 返回一个用于构造HTTP响应体的可迭代对象
1 | |
1 2 3 4 5 6 7 | |
- WSGI应用的运行
-
WSGI应用由WSGI服务器(或称为WSGI容器)调用,它就是所谓的外部进程,负责Web服务器和WSGI应用之间的通信交互
-
WSGI的运行过程
12.2.3 WSGI 服务器
- 简易WSGI服务器
1 | |
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | |
- Python内置的WSGI参考服务器
1 | |
1 2 3 4 5 6 7 8 | |
生产环境中常用的WSGI服务器
-
常用的WSGI服务器有
uWSGI、Gunicorn、CherryPy、Tornado、Paste、Waitress等 -
Waitress是一个纯Python的WSGI 服务器,安装使用非常方便, pip install waitress
1 2 3 | |
12.2.4 示例
1 | |
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 48 49 50 51 52 53 54 55 56 | |
12.3 异步服务器网关接口(ASGI)*
- 异步服务器网关接口(Asynchronous Server Gateway Interface, ASGI)是 WSGI 的 “精神继承者”
- 提供了对异步编程的支持
- 为新型协议或标准提供了扩展的可能性
- 在一定程度上兼容 WSGI
12.3.1 ASGI 应用
- 典型的ASGI应用
1 2 3 4 | |
scope:是一个字典,其中包含了服务器与客户端之间连接的详细信息(键和取值的格式在子协议中规定),其作用与WSGI应用中的环境变量参数env相似
- receive:是一个异步可等待对象,用于接收来自客户端的消息,用await语句异步运行后返回一个事件(Event),其中包含了客户端的消息内容
- send:也是一个异步可等待对象,用于向客户端发送消息,用await语句异步运行时以一个事件作为参数,其中包含了需要发送至客户端的消息内容
- 事件
- 字典,其键和取值由不同的子协议来确定
- HTTP 子协议
- WebSocket 子协议
- Lifespan 子协议
12.3.2 HTTP 子协议
scope字典
type:"http"asgi["version"]:ASGI 协议版本,当前最新版本为"3.0"asgi["spec_version"]:HTTP 子协议版本,取值为"2.0"或"2.1",默认为"2.0"http_version:"1.0"、"1.1"或"2"method:HTTP 请求方法(大写形式)scheme:协议名,取值为"http"或"https"path:HTTP 请求路径字符串(不包括查询串部分)raw_path:HTTP 请求头部路径部分的原始字节串,默认取值为Nonequery_string:查询字符串root_path:ASGI 应用的根路径,与 WSGI 中 SCRIPT_NAME 的含义相同,默认取 值为空字符串headers:HTTP 请求头,取值为形如[[header_name, header_value]]的可迭 代对象,header_name和header_value都是字节串,请求头的顺序与其在 HTTP 请 求中的出现顺序一致client:客户端地址,取值为[host, port],默认为Noneserver:服务器地址,取值为[host, port]或者[sock, None](sock为套接字对象),默认为None
请求事件
- 请求事件是
receive的异步调用返回结果,在 ASGI 应用主要用于获取 HTTP 请求正文,常用的键和取值 type: 取值为"http.request"body: HTTP 请求正文字节串,默认取值为b"",当请求正文较大时可以分块处理more_body: 取值为True或False,当取值为True时表示请求正文分块传输,并且还存在后续数据块,WSGI 应用应当等待所有数据块接收完毕后合并处理
响应开始事件
- 与 WSGI 应用中的start_response相似,表示开始构建 HTTP 响应
type: 取值为"http.response.start"status: HTTP 响应状态码(整数)headers: HTTP 响应头,取值为形如[[header_name, header_value]]的可迭代对象,header_name和header_value都是字节串,响应头的顺序与在 HTTP 响应 中的出现顺序一致
响应正文事件
- 包含了 HTTP 响应正文信息
type: 取值为"http.response.body"body: HTTP 响应正文字节串,默认取值为b"",响应正文也可以分块处理more_body:取值为True或False,当取值为True时表示还存在后续块
12.3.3 ASGI 服务器
1 | |
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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | |
12.3.4 示例
1 | |
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 48 49 50 51 52 53 | |
12.4 Web 应用框架
12.4.1 Web 框架的基本概念
- Web 框架
- Web 框架对 Web 应用程序开发过程中的通用部分进行了抽象和封装,使得 Web 应用程序开发者不必关心底层的实现细节,大大降低了开发的难度和成本
- Python 中的 Web 框架本质上就是一个 WSGI 应用或 ASGI 应用
- Web 框架的其他功能
- 安全问题
- URL路由
- Cookie使用
- 会话管理
- 模板引擎
- 数据库访问
- ... ...
- 常见 WSGI 框架
- Flask、Django、Tornado、Bottle等,
- 常见ASGI 框架
- FastAPI、Django Channels、Starlette
12.4.2 WSGI 框架
- 工具(AGSI框架也会用到)
1 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | |
- 简易WSGI框架
1 | |
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 | |
- WSGI Web 框架的应用
1 | |
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 | |
Flask
Flask是一个著名的“微型”Python Web开发框架
- “微型”指的是Flask仅保持一个小而简单但是足够强大、可扩展性良好的核心
- 默认情况下Flask仅包含基本的Web请求响应以及URL路由等核心功能,不过利用丰富的扩展可以非常方便地添加数据库对象关系映射、模板引擎、表单验证等功能,从而打造与项目相适应的Web开发框架
- 安装
- pip install flask
- Flask依赖于Werkzeug和 Jinja2
- Werkzeug是一个WSGI的工具包实现了WSGI的底层功能如请求/响应对象对象的构建、URL路由、环境配置等
- Jinja2是一个模板引擎
(1)基本应用
1 2 3 4 5 6 7 8 9 | |
(2)URL路由
- 两种方式:
add_url_rule方法route装饰器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
- URL变量处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
- URL变量转换器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
- 常用变量转换器
- int转换器
<int:param>:接收整数 - float转换器
<float:param>: 接收浮点数 - string转换器
<string:param>: 接收string类型(默认转换器) - path转换器
<path:param>:和默认的相似,但也接收斜线 - 自定义转换器(继承
werkzeug.routing.BaseConverter,添加到字典app.url_map.converters之中)
(3)request对象
request对象的属性method:当前请求方法;Form:包含表单参数及其值的字典;args:查询字符串中的参数;Cookies:Cookie字典;files:文件上传的相关数据。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
(4)模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | |
- jinja2
- 控制结构
{% %} - 变量取值
{{ }} - 注释
{# #} - for循环
1 2 3 4 5 | |
safe:不对字符串进行转义;
- capitialize:字符串首字母大写;
- lower:字符串小写;
- upper:字符串大写;
- title:单词首字母大写;
- trim:去除字符串两端空格;
- striptags:去除字符串中所有HTML;
- join:拼接多个值为字符串;
- replace:字符串替换;
- round:四舍五入;
- int:字符串转整型。
(5)静态文件处理
- 静态文件主要包括图片、视频、javascript、css等,其特点是数量较多、不会发生变化、不需要Python代码介入
1 2 | |
(6)Cookie与Session
- Cookie
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | |
- Session
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 | |
(7) 拦截器
1 2 3 | |
(8) 部署
- Nginx配置
1 2 3 4 5 6 7 8 9 | |
- WSGI服务器
-
端口为9000
-
Ningx命令
nginx:启动ningxnginx -s reload:重新加载nginx配置nginx -s stop:关闭nginx
12.4.3 ASGI 框架 *
- 简易 ASGI Web 框架
1 | |
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 48 49 50 51 52 53 | |
- ASGI Web 框架的应用
1 | |
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 | |
12.5 Web 开发中的设计模式
12.5.1 MVC 模式
MVC是一种软件的开发模式,将软件的业务逻辑、数据与界面显示相分离,从而降低它们之间的耦合性,以便于代码的重用、重构与维护。
- 模型(Model):负责封装应用的业务逻辑数据及相关操作方法,例如数据库的查询、更新等操作;
- 视图(View):负责呈现业务逻辑的处理结果;
- 控制器(Controller):负责控制应用的业务流程,对模型和视图进行组织、整合。
- MVC的优势
- 开发效率高
- 可维护性好
- 代码复用度高
- 便于设计
-
利于实现工具化和自动化
-
Web 开发中的 MVC 模式
- HTTP 协议的请求/响应访问模式使得模型不能主动向视图发送消息
12.5.2 MVC 模式的变种
- MTV(Model-Template-View)
- 模型:也称为数据存取层,负责数据库的访问与数据验证等
- 模板:也称为表现层,负责页面和数据的显示
- 视图:也称为业务逻辑层,根据业务逻辑调用模型获取业务逻辑数据,然后将业务逻辑数据与模板结合生成响应信息
- MVP(Model-View-Presenter)
- 模型
- 视图
- Presenter:MVC 模式中的控制器,不过它主要负责业务逻辑处理
- MVVM(Model-View-ViewModel)
- Model
- View
- ViewModel
- 视图与 ViewModel 之间的数据绑定
本页面的全部内容在 生信资料 bio.0594codes.cn 和 莆田青少年编程俱乐部 0594codes.cn 协议之条款下提供,附加条款亦可能应用