Please enable Javascript to view the contents

Django Restful 接口之 Tastypie

 ·  ☕ 5 分钟

1. Restful

REST,是Representational State Transfer的缩写,表现层状态转化。Restful,是一种开发理念,万维网软件架构风格。

1.1 Restful特点

  • 抽象资源
    图片、文本、歌曲、视频都是一种资源实体,在网络上,被抽象为资源。在Restful中,JSON常被用作这些资源的载体,统一对外提供数据信息。
  • 统一接口
    对数据的增删改查,分别对应于不同的HTTP方法。
  • GET(SELECT):从服务器取出资源(一项或多项)。
  • POST(CREATE):在服务器新建一个资源。
  • PUT(UPDATE):在服务器更新资源(客户端提供完整资源数据)。
  • PATCH(UPDATE):在服务器更新资源(客户端提供需要修改的资源数据)。
  • DELETE(DELETE):从服务器删除资源。
  • HEAD:获取资源的元数据。
  • OPTIONS:获取信息,关于资源的哪些属性是客户端可以改变的。

1.2 Restful规则

  • API URL前缀。为了兼顾API的扩展性,建议API的URL前缀设置为 http://example.com/api/v1/
  • URL中只能有名词。比如资源名和参数,http://example.com/api/v1/user/?id=1
  • 操作使用HTTP头设置。常见的有五种HTTP方法,GET、POST、PUT、PATCH、DELETE ,还有两个不常见的动词,HEAD、OPTIONS。用法:
    • GET /zoos/:列出所有动物园
    • POST /zoos/:新建一个动物园
    • GET /zoos/ID/:获取某个指定动物园的信息
    • PUT /zoos/ID/:更新某个指定动物园的信息(提供该动物园的全部信息)
    • PATCH /zoos/ID/:更新某个指定动物园的信息(提供该动物园的部分信息)
    • DELETE /zoos/ID/:删除某个动物园
    • GET /zoos/ID/animals:列出某个指定动物园的所有动物
    • DELETE /zoos/ID/animals/ID/:删除某个指定动物园的指定动物
  • 过滤规则
  • ?limit=10:指定返回记录的数量
  • ?offset=10:指定返回记录的开始位置。
  • ?page=2&per_page=100:指定第几页,以及每页的记录数
  • ?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序
  • ?animal_type_id=1:指定筛选条件

2. Tastypie

2.1 简介

Tastypie是基于Django的Restful api开发框架。通过简单的配置,就能对外提供Restful 风格的接口。

2.2 安装配置

1
pip instal django-tastypie

settings.py配置

1
2
3
 INSTALLED_APPS = (
    'tastypie',
)
1
python manage.py syncdb

2.3 授权Authorization

如果需要对接口的权限进行限制,Tastypie也提供相应的支持。

第一步,继承Authorization类实现MyAuthorization权限管理类。
需要实现的函数有:

  • def read_list(self, object_list, bundle)
  • def read_detail(self, objec_list, bundle)
  • def create_detail(self, object_list, bundle)
  • def update_list(self, object_list, bundle)
  • def update_detail(self, object_list, bundle)
  • def delete_list(self, object_list, bundle)
  • def delete_detail(self, object_list, bundle)

第二步,在Resource的Meta中,指定权限管理实例

1
2
class Meta(BaseMeta):
      authorization = MyAuthorization()

2.4 捆对象 Bundles

在定制Resource的过程中,不可避免的会使用捆对象,这是一个抽象的概念,代表了获取资源,或者写入资源过程中对单个资源的封装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class BucketObject(object):
    def __init__(self, initial=None):
        self.__dict__['_data'] = {}

        if hasattr(initial, 'items'):
            self.__dict__['_data'] = initial

    def __getattr__(self, name):
        return self._data.get(name, None)

    def __setattr__(self, name, value):
        self.__dict__['_data'][name] = value

    def to_dict(self):
        return self._data

这里的BucketObject,并不对应任何的Model,只是当做对资源的一次打包,可以是几个model的合集,也可以是接口访问后封装的数据。

2.5 ModelResource

ModelResource 是基于已有Model提供Restful API。

第一步,创建resource资源

reasource.py

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
from tastypie.resources import ModelResource
from .models import QuickView
class QickViewResource(ModelResource):
    class Meta:
        # 定义查询范围
        queryset = QuickView.objects.all()
        # 定义资源名
        resource_name = 'QucikView'
        # 其他配置
        excludes = ['create_time', 'update_time']

第二步,配置url路由,注册接口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
from tastypie.api import Api
from ci.api.resources import QickViewResource
# 创建API V1版本,URL形式为/api/v1/
api_v1 = Api(api_name='v1')
# 注册资源
api_v1.register(QickViewResource())
# 新增资源注册放在这里

urlpatterns = patterns('',
                      (r'^api/', include(api_v1.urls)),
                      )

第三步,开始使用

/api/v1/?format=json

查看api v1注册的全部资源,list_endpoint表示资源端点,schema提供的URL可以查看字段和使用规则。

1
2
3
4
5
6
{
    QucikView: {
        list_endpoint: "/api/v1/QucikView/",
        schema: "/api/v1/QucikView/schema/"
    }
}

/api/v1/QucikView/schema/?format=json

给出了基本的操作权限,默认参数,返回对象的字段和字段提示等。

 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
{
    allowed_detail_http_methods: [
        "get",
        "post",
        "put",
        "delete",
        "patch"
    ],
    allowed_list_http_methods: [
        "get",
        "post",
        "put",
        "delete",
        "patch"
    ],
    default_format: "application/json",
    default_limit: 20,
    fields: {
        app_id: {
            blank: false,
            default: "No default provided.",
            help_text: "Unicode string data. Ex: "Hello World"",
            nullable: false,
            primary_key: false,
            readonly: false,
            type: "string",
            unique: false,
            verbose_name: "业务ID"
        }
}

/api/v1/QucikView/?format=json&limit=1

获取资源的QucikView的列表,如果有分页,tastypie还会给出提示连接

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
{
    meta: {
        limit: 1,
        next: "/api/v1/QucikView/?offset=1&limit=1&format=json",
        offset: 0,
        previous: null,
        total_count: 8
    },
    objects: [
        {
            app_id: "1",
            create_time: "2017-06-12T11:42:30.071000",
            data: "{sadknlsakbf}",
            id: 1,
            index: 0,
            is_deleted: false,
            pipeline_id: "2",
            resource_uri: "/ci/api/v1/QucikView/1/"
        }
    ]
}

2.6 Resource

如果需要基于第三方接口,或者几个Model,或者非ORM的数据源,对外提供Restful的接口,ModelResource 可能并不适用。tastypie 提供了Resource 类来抽象这部分资源。

这里主要是理解,上面提到的 捆对象 Bundles 概念,写一个BucketObject类,将资源封装在其中。

reasource.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
class BuildResource(Resource):
    buildNo = fields.CharField(attribute='buildNo')
    starter = fields.CharField(attribute='starter')
    duration = fields.CharField(attribute='duration')
    endTime = fields.CharField(attribute='endTime')
    csReleaseNote = fields.CharField(attribute='csReleaseNote')
    statusBuild = fields.CharField(attribute='statusBuild')
    totalBuildNum = fields.CharField(attribute='totalBuildNum')

    class Meta:
        resource_name = 'BuildList'
        allowed_methods = ['get']
        object_class = BucketObject
        authorization = Authorization()

    def obj_get_list(self, request=None, **kwargs):
        if not request:
            request = kwargs['bundle'].request
        return self.get_object_list(request)

    def get_object_list(self, request):
        results = []
        key_list = ("buildNo", "starter", "duration", "endTime", "csReleaseNote",
                    "statusBuild", "statusBuild", "totalBuildNum")
        new_obj = BucketObject()
        for key in key_list:
            # 这里调用第三方接口,或者取其他Model数据,填充BucketObject
            setattr(new_obj, key, key+"_vaule")
        results.append(new_obj)
        return results

url中的配置和ModelResource一样。这里仅仅实现了get的函数重载,如果对应其他操作,也需要重写相应的函数。一共有九个:

  • detail _uri _kwargs
  • get
  • object_list
  • obj _get _list
  • obj _get
  • obj _create
  • obj _update
  • obj _delete_list
  • obj _delete
  • rollback

3. 参考


微信公众号
作者
微信公众号