昨天有位同学私信我,说他所在的公司的不少项目都有个controllers.py的文件或者controllers的目录用来存放视图。但是和他理解的Python Web框架的设计模式不太一样,问我MVC/MVT到底怎么区分。听他一开始说,我为之一怔,因为我身边的人就有写controllers的… 不过我没有去验证这只是只是目录的名字而已。
今天我和大家聊聊我的理解。
复杂的软件必须有清晰合理的架构,否则无法开发和维护。 - 阮一峰
MVC(Model View Controller 模型-视图-控制器)是一种Web架构的模式(本文不讨论桌面应用的MVC),它把业务逻辑、模型数据、用户界面分离开来,让开发者将数据与表现解耦,前端工程师可以只改页面效果部分而不用接触后端代码,DBA可以重新命名数据表并且只需更改一个地方,无需从一大堆文件中进行查找和替换。MTC模式甚至还可以提高代码复用能力。现在几乎所有的Web开发框架都建立在MVC模式之上。 当然,最近几年也出现了一些诸如MVP, MVVM之类的新的设计模式。 但从技术的成熟程度和使用的广泛程度来讲,MVC仍是主流。
MVC三要素:
MVC的特点是单向的:
1. 浏览器发送请求 2. Contorller和Model交互获取数据 3. Contorller调用View 4. View渲染数据返回
和Rails、Spring、Laravel等其他语言的Web框架不一样,在Python的世界中,基本(除了Pylons)都使用了MVC的变种MTV(Model Templates View 模型-模板-视图):
注意啦:MVC中的View的目的是「呈现哪一个数据」,而MTV的View的目的是「数据如何呈现」。
也就是把MVC中的View分成了视图(展现哪些数据)和模板(如何展现)2个部分,而Contorller这个要素由框架自己来实现了,我们需要做的就是把(带正则表达式的)URL对应到视图就可以了,通过这样的URL配置,系统将一个请求发送到一个合适的视图。
需要注意,Flask这种微框架就不是一个MVC模式的,因为它没有提供Model,除非集成了SQLAlchemy之类的ORM进来。
所以大家最常见的Python Web项目的目录风格是这样的:
├── app.py ├── models # 目录 ├── requirements.txt ├── static └── views # 目录
或者:
├── app.py ├── models.py ├── requirements.txt ├── static └── views.py
Django官方网站 、 《基于python的web应用开发实战》书中的项目flasky 、 Flask官方网站 、 知名的Django API框架 等项目都是这种命名原则。
MVVM(Model View ViewModel)是一种基于前端开发的架构模式,但是会写前端页面的Python Web开发显然也是有必要了解的。它的核心是提供对View和ViewModel的双向绑定,View和Model之间并没有直接的联系,而是通过ViewModel进行交互,View的变动,自动反映在ViewModel上,反之亦然,这样就保证视图和数据的一致性。
ViewModel是Model和View之间的桥梁,它的设计原则是:
现在比较流行的MVVM框架是Vue.js和AngularJS。不能不感叹下,前端太能玩了。
我为什么聊MVVM呢,其实是我注意到现在有一些现象:
当然,黑猫白猫能抓老鼠就是好猫,我说的是没有用对地方。
现在前后端交互通常是如下流程:
我们设想一个复杂的场景下,有个页面需要后端的数据来生成界面,通过在界面的某些控件输入或者触发事件的方式重新获取数据变换成其他界面。注意,整个过程页面的URL没有发生跳转。
传统的类似jQuery + Template的方式有以下痛点:
其实数据和界面的变更之间,一般都是存在对应关系的。如果能够引入一种绑定关系,经过一系列的配置过程,使得以后每次数据发生变更,界面都会自动跟着作对应变动;界面上的操作,也会自动更新到数据,那开发过程就会非常省事了,绝大部分此类操作都会转化为配置,供绑定框架用来建立数据和界面之间的关联关系。MVVM框架可以帮助你可以减少大量的DOM操作没提高渲染性能。
我实际工作中很多内部用到类似后台的项目,大多设计成只用基本模板index.html,其中引用了由webpack编译react/vue源码生成的javascript文件的方式,后端提供API。但是并不代表后端模板的没落:
所以大家还是得好好学Jinja2、Mako吧。