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. 参考
- https://codeslashslashcomment.com/2012/11/13/call-diagram-of-django-tastypie-resource-get_list-method/
- http://django-tastypie.readthedocs.io/en/latest/tutorial.html