Django 快速 RESTful API 开发

2018-11-09

前言

在后端开发中,最核心、最基础的事情是定义数据结构,定义好数据结构后,需要对外提供增删改查(CRUD)的接口,CRUD 是个苦力活。有没有可能开发者只关心数据结构定义,由网络框架自动提供一系列 CRUD 方法呢?答案是肯定的。

虽然如此,我在工作中还是看到人们一遍遍、一层层、反反复复地写这些重复代码,以至于占用了工作中的想当一部分精力。后端工作的核心不应该浪费在反复刷胶水上,而是应该放在更深层次的架构设计和商业模式思考上。

在本文中,我选用 Django 网络框架,结合它的 RESTframework 扩展,来介绍这种技术。本文假设读者有后端开发基础,并熟悉 Django 框架的使用,不是一个 Step by Step Tutorial。

定义模型

假设我们要搭建一个应用商店(AppStore)应用,Model 如下:

app/models.py:

class App(models.Model):
    name = models.CharField(max_length=50)
    developer = models.ForeignKey(Developer, on_delete=models.CASCADE, null=True)
    appid = models.CharField(max_length=20)
    intro = models.TextField()

developer/models.py:

class Developer(models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

绑定框架

上面的模型定义好,API 开发工作就完成了 80% 了,剩下的工作都交给框架,以 app application

为例。

创建 app 的序列化器 app/serializers.py:

class AppSerializers(ModelSerializer):
    class Meta:
        model = App
        fields = ('name', 'developer', 'appid', 'intro')

Magic happens 的地方,自动创建一系列 API app/views.py:

from rest_framework import generics

from .models import App
from .serializers import AppSerializers

class AppList(generics.ListCreateAPIView):
    queryset = App.objects.all()
    serializer_class = AppSerializers
    filter_fields = ('developer',)

class AppDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = App.objects.all()
    serializer_class = AppSerializers

最后,注册一下 URL,app/urls.py:

from django.urls import path
from app import views

urlpatterns = [
    path('apps/', views.AppList.as_view()),
    path('apps/<int:pk>', views.AppDetail.as_view())
]

大功告成!

至此,工作就完成了!我省略了一些细碎的步骤,那些都属于 Django 基础,不再赘述。

我们获得了哪些接口呢?

接口METHOD说明
/appsGET列表获取(支持分页)
/appsPOST列表提交
/apps/?developer=1GET字段检索
/apps/1GET单条检索
/apps/1DELETE单条删除
/apps/1POST单条创建 or 更新
/apps/1UPDATE单条更新

从中可见,常用的 RESTful 都已经创建完成,我们一共写了不到 20 行代码。

到这里并没有结束,restframework 还自动为我们创建了一个调试网站:

我们在其中可以校验数据类型、添加修改数据等进行快速调试。

Options

我还学习到 RESTful 有一个 OPTIONS 方法,这个方法的作用是返回接口的数据定义:

{
    "name": "App Detail",
    "description": "",
    "renders": [
        "application/json",
        "text/html"
    ],
    "parses": [
        "application/json",
        "application/x-www-form-urlencoded",
        "multipart/form-data"
    ],
    "actions": {
        "PUT": {
            "name": {
                "type": "string",
                "required": true,
                "read_only": false,
                "label": "Name",
                "max_length": 50
            },
            "developer": {
                "type": "field",
                "required": false,
                "read_only": false,
                "label": "Developer"
            }
        }
    }
}

如此说来,我们在 App 中根本都不需要再写 Entity 了。直接访问接口得到 JSON 数据,根据本地缓存的 OPTIONS 进行解析,如果解析失败,则去拉取最新的 OPTIONS 进行解析。

没想到不仅后端省事,前端都跟着省事了。先进技术真是第一生产力!

高级功能

CRUD 太基础了,在商业应用中还需要支持的特性有:

  • 鉴权
  • 校验
  • 限流
  • 缓存
  • 版本管理
  • ……

这些 restframework 都是支持的,具体参见其官网的 API Guide 部分。基本上都可以通过几行代码实现。

总结

本文的主要目的不是安利 Python、Django,因为在公司里 PHP 还是主流,并且 PHP 工程师在招人上有极大优势,我无意改变。

我的主要目的是分享快速 RESTful API 开发的思想,因为我看到业务中还有很多人在一遍一遍、反反复复地写这些本应该自动生成的接口,浪费了大量的精力,以至于反而没有时间对架构、业务进行更好的设计。

语言、框架不是障碍,PHP 与 Python 一样都是脚本语言,上面的这些特性在 PHP 中同样能够轻易实现。后续我会去看看在 Laravel 中是否有同类的框架。