AberSheeran
Aber Sheeran

MVT 模式在 API 中的应用

起笔自
所属文集: Django-Simple-Api
共计 1437 个字符
落笔于

MVT 模式指一种程序解耦的模式。M 是 Model,用于管理数据;V 是 View,用于处理具体业务逻辑;T 是 Template,用于把编程语言的对象转成用户阅读的页面。现在工作细化,后端开发已经不会去使用 Template 渲染页面了,这项工作往往是前端开发来做。

但 MVT 模式并没有落后于时代。只需要转换一下思路,就会发现 MVT 仍然是很好的程序解耦的模式——只需要把 T 换成 S(Serialization)。

以 Django 为例,传统的 MVT 开发里是这么写代码的——把 View 里准备好的 Python 对象传给 Template,然后渲染出一个 HTML 字符串。

def homepage(request):
    return render("template.html", context={"key": value})

如果写一个接口则是这么写——把 View 里准备的 Python 对象转成 JSON 字符串。

def homepage(request):
    return JSONResponse({"key": value})

两者本质上没有区别,都是把编程语言里的对象转成能让用户理解的东西。只不过 MVT 模式里,Template 的结果直接面向浏览器,让浏览器渲染给用户看;MVS 模式里,序列化的结果是给客户端,客户端使用数据渲染出结果给用户看。

许多像我一样不爱用 django-rest-framework 的 Serializer 功能的人,往往都会自己动手在 View 里处理 Python 对象,把它们转成 JSON 标准库能够转换的格式。但这其实会导致许多重复性的工作,比如一个 Model 或一个 QuerySet 转成 JSON 字符串,这应当是可以自动化的(可参见一种序列化 Django model 的新思路)。

在我写了两个需要手动序列化的项目之后,我突然觉得这么多重复性工作太愚蠢了,我为什么不把 Index.py 里的先进经验搬到 Django 里来呢。写一个中间件(能同时作用在所有视图上的装饰器)来捕捉响应值,然后通过不同的响应结果去寻找不同的处理函数,转换成不同的响应结果。于是就先有了上面自动序列化 Django Model 一文,然后有了此文。

这样处理好处是十分明显的,比如在视图函数里只需要像下面这样写,在中间件里它会自动转换成内容为 {"message": "Message"} 的 JSON 响应对象。当客户端要求修改格式时,比如要求在每个响应里都加上 {"data": ...},不需要到每个视图里的每个返回点进行修改格式。

def find(request):
    ......
    return "Message"

了解了 MVS 模式,你再也不需要在视图函数里做一些业务逻辑无关的处理了。比如客户端要求序列化 datetime 的结果带上时区信息。视图函数(View)里不需要做任何额外的处理,只需要在业务逻辑完成后返回结果对象就行了。渲染成什么格式,XML 还是 JSON,带时区还是不带时区,这些都由中间件(Serialization)来做。

最后,由于那个序列化中间件仓促而成,所以就不开源出来了。实现思路和代码可以参考 Index.py 里的部分。

如果你觉得本文值得,不妨赏杯茶
一种序列化 Django model 的新思路
没有下一篇