标题: 用 Python 撸一个 Web 服务器-第3章:使用 MVC 构建程序 [打印本页] 作者: 伤心客 时间: 2024-6-13 06:14 标题: 用 Python 撸一个 Web 服务器-第3章:使用 MVC 构建程序 Todo List 程序先容
我们将要编写的 Todo List 程序包含四个页面,分别是注册页面、登录页面、首页、编辑页面。以下分别为四个页面的截图。
注册页面:
注册
登录页面:
登录
首页:
首页
编辑页面:
编辑
程序页面非常简洁,乃至有些 Low。但这足够我们学习开发 Web 服务器程序原理,页面样式的题目并不是我们本次学习的重点,所以读者不必纠结于此。
Todo List 程序功能大概分为两个部分,一部分是 todo 管理,包含增删改查底子功能;另一部分是用户管理,包含注册和登录功能。
初识 MVC
先容了 Todo List 程序的页面和功能,接下来我们就要思考怎样设计程序。
以客户端通过欣赏器向服务器发送一个获取应用首页的哀求为例,来分析下服务器在收到这个哀求后都需要做哪些事情:
首先服务器需要对哀求数据进行解析,发现客户端是要获取应用首页。
然后找到代表首页的 HTML 文件,读取 HTML 文件中的内容。
最后将 HTML 内容组装成符合 HTTP 规范的数据进行返回。
这是一个较为抱负的情况,因为 HTML 页面内容是固定的,我们不需要对其进行其他处理,直接返回给欣赏器即可。通常我们管这种页面叫静态页面。
但现实情况中,Todo List 程序首页内容并不是一成不变的,而是动态变化的。首页 HTML 文件中只定义底子结构,具体的 todo 数据需要动态填充进去。所以一个更加完整的服务器处理哀求的过程应该像下面如许:
首先服务器需要对哀求数据进行解析,发现客户端是要获取应用首页。
然后从数据库中读取 todo 数据。
接着找到代表首页的 HTML 文件,读取 HTML 文件中的内容。
再将 todo 数据动态添加到 HTML 内容中。
最后将处理好的 HTML 内容组装成符合 HTTP 规范的数据进行返回。
现在已经知道了服务器处理哀求的完整过程,我们就可以设计服务器程序了。试想一下,如果 Todo List 程序都像 Hello World 程序一样把代码都写在一个 Python 文件中也不是不可以。但如许的代码显然不具备良好的扩展性和可维护性。那么更好的设计模式是什么呢?
其实对于 Web 服务器程序的设计,业界早已达成了一个普遍的共识,那就是 MVC 模式:
M(Model):模型,用来存储和处理 Web 应用数据。
V(View):视图,格式化显示 Web 应用页面。
C(Controller):控制器,负责底子逻辑,如从模型层读取数据并将数据填充到视图层,然后返回响应。
通过 MVC 的分层结构,能够让 Web 应用设计更加清晰,可以很轻易的构建可扩展、易维护的代码。模型层,说直白些其实就是用来读写数据库的 Python 代码,新增 todo 的时候,可以通过模型层的代码将数据生存到数据库中,访问首页时需要展示全部已生存的 todo,这时可以通过模型层的代码从数据库中读取全部 todo。视图层,可以将其简单的明白为 HTML 模板文件的聚集。控制器起到粘合的作用,它将从模型层读取过来的数据填充到视图层并返回给欣赏器,或者将欣赏器通过 HTML 页面提交过来的数据解析出来再通过模型层写入数据库中。
我画了一个示例图,来资助你明白 MVC 模式。图中标注了欣赏器发起一个哀求到获得响应,中心履历的完整过程。
照旧以客户端哀求 Todo List 程序首页为例,一个完整的哀求过程如下:
欣赏器发起哀求。
哀求到达服务器后首先辈入控制器,然后控制器从模型获取 todo 数据。
模型操纵数据库,查询 todo 数据。
数据库返回 todo 数据。
模型将从数据库中查询的 todo 数据返回给控制器,控制器暂时将数据生存在内存中。
控制器从视图中获取首页 HTML 模板。
控制器将从模型查出来的 todo 数据填充到首页 HTML 模板中,并组装成符合 HTTP 规范的数据。
服务器返回响应。
其实 MVC 是一个宏观上的分层,具体细节部分还需要根据我们设计程序的粒度来进行处理,好比有些逻辑既可以写在控制器层,也可以写在模型层,乃至我们还可以在 MVC 的底子上扩展更多的分层。这些都需要联合具体的业务逻辑来决定。
构建 Todo List 程序
学习了 MVC 模式,我们就可以根据 MVC 模式来试着构建 Todo List 程序了。
Todo List 程序分两部分:todo 管理、用户管理。在项目初期,我们肯定不会思量的太过全面。所以可以先不思量用户管理功能部分的实现,先只思量怎样实现 todo 管理功能。
Todo List 程序目录结构设计如下:
todo_list
├── server.py
└── todo
├── \_\_init\_\_.py
├── config.py
├── controllers.py
├── db
│ └── todo.json
├── models.py
├── templates
│ ├── edit.html
│ └── index.html
└── utils.py
复制代码
这里以 todo_list/ 作为程序的根目录,根目录下包含 server.py 文件和 todo/ 目录。此中 server.py 主要功能就是作为一个 Web Server 来接收哀求和返回响应,它是 Todo List 程序的入口和出口。而 todo/ 目录则是 Todo List 程序处理业务逻辑的核心。
todo/ 目录下的 __init__.py 将 todo/ 文件夹标记为一个 Python 包。 config.py 用于存储一些项目的底子设置。utils.py 是一个工具集,里面可以定义一些供其他模块调用的类和方法。db/ 目录作为 Todo List 程序存储数据的目录,db/todo.json 用来存储全部的 todo 内容。剩下还有两个 .py 文件和一个目录没有先容,相信你已经猜到了 models.py、templates/、controllers.py 分别对应了 MVC 模式中的模型、视图、控制器。models.py 中编写操纵 todo 数据的代码,templates/ 目录用来存放 HTML 模板文件,templates/index.html 是首页,templates/edit.html 是编辑页面,controllers.py 编写负责程序控制的底子逻辑代码。
我们对项目的目录结构有了一个概览,这里我要夸大一下 db/ 目录的作用。我们在开发整个 Todo List 程序的过程中都不会使用现实的数据库程序,项目中全部需要存储的数据都生存在 db/ 目录下的文件中。在开发 Web 程序时,需要用到数据库的目的就是为了存储数据,对于 Todo List 程序来说使用文件同样能满意需求,同时能够照顾到对数据库不了解的读者。
Todo List 首页开发
Todo List 程序目录结构构建完成后就可以动手开发程序了,我们可以从一个哀求履历的过程来着手。
一个哀求发送到服务器,首先服务器需要有一个能够接收哀求的入口,在程序根目录 todo_list/ 下的 server.py 就是这个入口。server.py 文件代码如下:
t = threading.Thread(target=process_connection, args=(client,))
t.start()
if \_\_name\_\_ == '\_\_main\_\_':
main()
复制代码
首先完成之前未写完的 process_connection 函数。将原来标记 TODO 注释的地方更换成了如下代码:
\# 解析请求报文,构造请求对象
request = Request(request_message)
\# 根据请求对象构造响应报文
response_bytes = make_response(request)
\# 返回响应
client.sendall(response_bytes)
复制代码
新增了一个 make_response 函数,方便用来根据哀求对象构造响应报文。函数中我写了比力详细的注释,你可以根据注释内容读懂代码逻辑。
最后给出首页 todo/templates/index.html 的 HTML 代码:
<!--todo_list/todo/templates/index.html-->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Todo List</title>
<style>
\* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
a {
text-decoration: none;
outline: none;
color: #000000;
}
h1 {
margin: 20px auto;
}
.container {
display: flex;
justify-content: center;
align-items: center;
}
.container ul {
width: 100%;
max-width: 600px;
}
.container ul li {
height: 40px;
line-height: 40px;
margin-bottom: 4px;
padding: 0 6px;
display: flex;
justify-content: space-between;
background-color: #d2d2d2;
}
</style>
</head>
<body>
<h1 class="container">Todo List</h1>
<div class="container">
<ul>
<li>
<div>Hello World</div>
</li>
</ul>
</div>
</body>
</html>
复制代码
HTML 代码比力简单,此中顶部写了一些底子的 CSS 样式,都很轻易看懂,这里不再解说。
接下来在终端中,进入 todo_list/目录下,使用 Python 运行 server.py 文件,看到如下打印效果说明程序已经正常启动:
运行 Todo List 服务器
打开欣赏器,地点栏输入 http://127.0.0.1:8000/ 或者 http://127.0.0.1:8000/index,你将看到 Todo List 程序首页:
Todo List 首页
至此,Todo List 程序首页初步完成。不过我想许多读者看到这里会产生疑惑,说好的 MVC 呢,现在为止我们并没有编写一行模型层的代码,并且首页的 HTML 内容也不是动态填充的。没错,为了能够尽快让 Todo List 程序跑起来,我有意的避开了这两个题目,下一章我们再来办理这两个题目。
本章源码:chapter3
原文出处: https://jianghushinian.cn