模型 - 视图 - 控制器模式
MVC 不仅仅是一种实现用户界面的软件模式,同时也是一种易于修改和维护的架构。通常 MVC 模式将应用程序分为 3 个基本部分:模型(Model)、视图(View)和控制器(Controller)。这 3 个部分相互关联,有助于将信息的处理与信息的呈现分开。
MVC 模式的工作机制为:模型提供数据和业务逻辑(如何存储和查询信息),视图负责数据的展示(如何呈现),而控制器则是两者之间的粘合剂,根据用户要求的呈现方式协调模型和视图。视图和控制器依赖于模型,但模型是可以独立工作的。
- 模型:定义针对数据的所有操作(如创建、修改和删除等),并提供与数据使用有关的方法
- 视图:提供相应的方法,帮助根据上下文和应用程序的需要构建 Web 或 GUI 界面
- 控制器:从请求接收数据,并将其发送到系统的其他部分。需要提供用于路由请求的方法
MVC 模式的主要意图:
- 将数据和数据的展示隔离开
- 使类的维护和实现更加简单
- 灵活地改变数据的存储和显示方式,两者相互独立
模型是应用程序的基石,提供客户端请求的数据,必须在多个操作中保持一致。
视图用来将数据展示在接口上供用户查看。可以独立开发,但不应包含复杂的逻辑;需要足够灵活,适应多种平台;应避免与数据库直接交互。
控制器应该作为模型和视图之间的粘合剂,要尽可能薄;不应该进行数据库调用或参与数据的展示。
示例代码
1 | class Model: |
现实世界中的 MVC 模式
目录结构:1
2
3
4
5
6mvc
├── server.py
└── templates
├── base.html
├── index.html
└── new.html
server.py
源代码: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
74import tornado
import tornado.web
import tornado.ioloop
import tornado.httpserver
import sqlite3
def _execute(sql):
db = sqlite3.connect('sqlite3.db')
cursor = db.cursor()
cursor.execute(sql)
res = cursor.fetchall()
db.commit()
db.close()
return res
class IndexHandler(tornado.web.RequestHandler):
def get(self):
query = "select * from task;"
todos = _execute(query)
print(todos)
self.render('index.html', todos=todos)
class NewHandler(tornado.web.RequestHandler):
def post(self):
name = self.get_argument('name', None)
query = "create table if not exists task (id INTEGER \
PRIMARY KEY, name TEXT, status NUMERIC);"
_execute(query)
query = "insert into task (name, status) values ('%s', %d);" % (name, 1)
_execute(query)
self.redirect('/')
def get(self):
self.render('new.html')
class UpdateHandler(tornado.web.RequestHandler):
def get(self, id, status):
query = "update task set status=%d where \
id=%s;" % (int(status), id)
_execute(query)
print(query)
self.redirect('/')
class DeleteHandler(tornado.web.RequestHandler):
def get(self, id):
query = "delete from task where id=%s;" % id
_execute(query)
self.redirect('/')
class RunApp(tornado.web.Application):
def __init__(self):
Handlers = [
(r'/', IndexHandler),
(r'/todo/new', NewHandler),
(r'/todo/update/(\d+)/(\d+)', UpdateHandler),
(r'/todo/delete/(\d+)', DeleteHandler),
]
settings = dict(
debug=True,
template_path='templates',
static_path='static',
)
tornado.web.Application.__init__(self, Handlers, **settings)
if __name__ == '__main__':
http_server = tornado.httpserver.HTTPServer(RunApp())
http_server.listen(5000)
tornado.ioloop.IOLoop.instance().start()
templates/base.html
源代码:1
2
3
4
5
6
7
8
9
<html>
<head>
{% block header %}{% end%}
</head>
<body>
{% block body %}{% end %}
</body>
</html>
templates/index.html
源代码: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{% extends 'base.html' %}
<title>ToDo</title>
{% block body %}
<h3>Your Tasks</h3>
<table border="1">
<tr align="center">
<td>Id</td>
<td>Name</td>
<td>Status</td>
<td>Update</td>
<td>Delete</td>
</tr>
{% for todo in todos %}
<tr align="center">
<td>{{ todo[0] }}</td>
<td>{{ todo[1] }}</td>
{% if todo[2] %}
<td>Open</td>
{% else %}
<td>Closed</td>
{% end %}
{% if todo[2] %}
<td><a href="/todo/update/{{todo[0]}}/0">Close Task</a></td>
{% else %}
<td><a href="/todo/update/{{todo[0]}}/1">Open Task</a></td>
{% end %}
<td><a href="/todo/delete/{{todo[0]}}">X</a></td>
</tr>
{% end %}
</table>
<div>
<h3><a href="/todo/new">Add Task</a></h3>
</div>
{% end %}
templates/new.html
源代码:1
2
3
4
5
6
7
8
9
10
11{% extends 'base.html' %}
<title>ToDo</title>
{% block body %}
<div>
<h3>Add Task to your List</h3>
<form action="/todo/new" method="post" id="new">
<p><input type="text" name="name" placeholder="Enter task" />
<input type="submit" class="submit" value="add" /></p>
</form>
</div>
{% end %}
运行 python server.py
命令,浏览 http://localhost:5000/ ,效果如下:
PS:需安装 tornado 模块(pip install tornado
)