目录

    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 安装配置

    pip instal django-tastypie
    

    settings.py配置

     INSTALLED_APPS = (
        'tastypie',
    )
    
    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中,指定权限管理实例

    class Meta(BaseMeta):
          authorization = MyAuthorization()
    

    2.4 捆对象 Bundles

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

    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

    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路由,注册接口

    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可以查看字段和使用规则。

    {
        QucikView: {
            list_endpoint: "/api/v1/QucikView/",
            schema: "/api/v1/QucikView/schema/"
        }
    }
    

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

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

    {
        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还会给出提示连接

    {
        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

    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. 参考