一个订单的功能,增删改查需要四个视图函数,对应四个 url
views.py
def get_order(request):
return HttpResponse('')
def add_order(request):
return HttpResponse('')
def del_order(request):
return HttpResponse('')
def update_order(request):
return HttpResponse('')
urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^get_order/', views.get_order),
url(r'^add_order/', views.add_order),
url(r'^del_order/', views.del_order),
url(r'^update_order/', views.update_order),
]
这样一旦功能多了起来,对应的 url 也就多了,显然不好处理。现在只写一个 url,对应四个功能,于是要在视图函数中判断
urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^order/', views.order),
]
views.py
def order(request):
if request.method == 'GET':
return HttpResponse('获取订单')
elif request.method == 'POST':
return HttpResponse('创建订单')
elif request.method == 'PUT':
return HttpResponse('更新订单')
elif request.method == 'DELETE':
return HttpResponse('删除订单')
这就是 restful
规范之一:根据 method
不同从而做不同的操作
上面的方法也可以基于 CBV 来实现:
urls.py
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^order/', views.OrderView.as_view())
]
views.py
from django.views import View
class OrderView(View):
def get(self, request, *args, **kwargs):
return HttpResponse('获取订单')
def post(self, request, *args, **kwargs):
return HttpResponse('创建订单')
def put(self, request, *args, **kwargs):
return HttpResponse('更新订单')
def delete(self, request, *args, **kwargs):
return HttpResponse('删除订单')
RESTful Api设计规范
协议
API 与用户的通信协议,总是使用 HTTPs 协议
域名
应该尽量将 API 部署在专用域名之下,如果确定 API 很简单,不会有进一步的扩展,可以考虑放在主域名之下。
版本
-
应该将API的版本放在URL中:https://www.qiuxirufeng.cn/api/v1.0
-
将版本号放在HTTP头信息中:https://www.qiuxirufeng.cn/students
路径
表示 API 的具体网址,每个网址代表一种资源,所以网址中不能有动词,只能有名词,并且所用的名词往往与数据库的表名对应。数据库中的表示记录同种数据的集合,所以 API 中的名词也应该使用复数。
示例:获取所有学生
- 错误写法:https://www.qiuxirufeng.cn/api/v1.0/getStudents/
- 正确写法:https://www.qiuxirufeng.cn/api/v1.0/students/
请求方法(method)
方式 | 解释 |
---|---|
GET | 从服务器获取资源(一项或者多项) |
POST | 在服务器新建一个资源 |
PUT | 在服务器更新资源(客户端提供改变后的完整资源) |
PATCH | 在服务器更新资源(客户端提供改的属性) |
DELETE | 从服务器删除资源 |
HEAD | 获取资源的元数据 |
OPTIONS | 获取信息,关于资源的哪些属性是客户端可以改变的 |
示例
描述 | 方式 |
---|---|
列出所有班级 | GET /grades/ |
获取某个指定班级编号的信息 | GET /grades/id |
列出某个指定编号的班级的所有学生 | GET /grades/id/students/ |
获取某个指定编号的学生信息 | GET /students/id |
创建一个学生 | POST /students/ |
更新某个指定学生的信息(信息全部由客户端提供) | PUT /students/id |
删除某个指定编号的学生 | DELETE /students/id |
删除某个指定班级的下的所有学生 | DELETE /grades/id/students/ |
过滤信息
如果资源数较多,服务器不能将所有数据一次全部返回给客户端,API 应该提供参数,通过在 url 上传参的形式传递搜索条件,过滤返回结果
示例
描述 | 方式 |
---|---|
指定返回记录的数量 | GET /students/?limit= |
指定返回记录的开始位置 | GET /students/?offset= |
指定返回第几页数据,以及每页的记录数 | GET /students/?page=&per_page= |
指定返回结果按照哪个属性排序,以及排序的顺序 | GET /students/?sortby=&order= |
指定筛选条件 | GET /students/?student_age_gt= |
注意:参数的设计允许存在冗余,即允许 API 路径和 URL 参数偶尔有重复
状态码
服务器向客户端返回的状态码和提示信息
错误处理
如果错误码是 4xx,就应该向用户返回错误信息,一般来说,返回的信息中将 error 作为键名,出错的信息作为键值即可
{
error: 'Invalid API KEY',
}
响应结果
针对不同的操作,服务器向用户返回结果应该符合规范
方式 | 描述 |
---|---|
GET /students/ | 返回资源对象的列表 |
GET /students/id/ | 返回单个资源对象 |
POST /students/ | 返回新生成的资源对象 |
PUT /students/ | 返回完整的资源对象 |
PATCH /students/ | 返回完整的资源对象 |
DELETE /students/id/ | 返回一个空文档 |
使用链接相关的资源(Hypermedia)
RESTful API 最好做到 Hypermedia,即返回结果中提供链接,链向了其他的 API 方法,使得用户不查看文档,也知道下一步应该做什么
示例
{
link:" www.qiuxirufeng.cn/grades/"
}
{
"link":{
"rel":"collection www.qiuxirufeng.cn/index/",
"href":"www.qiuxirufeng.cn/grades/",
"title":"List of Grades",
"type":"application/json",
}
}
'''
rel:表示这个 API 与当前网址的关系
href:表示 API 路径
title:表示 API 的标题
type:表示返回的类型
'''
其他:服务器返回的数据尽量使用 json 格式,避免使用 xml 格式