rest framework规范
网站的开发模式
网站的开发模式有两种:
- 普通开发模式(前后端一起写,django返回render redirct,httpresponse) 前后端分离:前端HTML页面通过ajax调用后端的restfulapi接口并用json进行数据交互
- 前端只能发送ajax请求,永远不用form表单了
- 后端只用Httpresponse返回json数据
什么是restful
REST 中文翻译为表述性状态转移(representational state transfer),它与技术无关是一种网络化超媒体应用的架构风格(规范)。我们建立api要遵守的一规则,但并不是必须的.它主要是用于构建轻量级的、可维护的、可伸缩的 Web 服务。基于 REST 的服务被称为 RESTful 服务。REST 不依赖于任何协议,但是几乎每个 RESTful 服务使用 HTTP 作为底层协议。
如何通俗易懂的理解restfull ?
用URL定位资源,用HTTP描述操作
RESTful 服务的目的
每个系统都使用资源。这些资源可以是图片,视频文件,网页,商业信息,或者在基于计算机的系统中可以被代表的任何事物。服务的目的是提供一个接口给客户端以便客户端能访问和操作这些资源.
URI 的设计只要负责把资源通过合理方式暴露出来就可以了。对资源的操作与它无关,操作是通过 HTTP动词来体现,所以REST 通过 URI 暴露资源时,会强调不要在 URI 中出现动词。
GET /rest/api/getDogs --> GET /rest/api/dogs 获取所有小狗狗 GET /rest/api/addDogs --> POST /rest/api/dogs 添加一个小狗狗 GET /rest/api/editDogs/:dog_id --> PUT /rest/api/dogs/:dog_id 修改一个小狗狗 GET /rest/api/deleteDogs/:dog_id --> DELETE /rest/api/dogs/:dog_id 删除一个小狗狗
左边的这种设计,很明显不符合REST风格,上面已经说了,URI 只负责准确无误的暴露资源,而 getDogs/addDogs...已经包含了对资源的操作,这是不对的。相反右边却满足了,它的操作是使用标准的HTTP动词来体现。
restful规范(建议)
restful是目前流行的api设计规范,目的是在url上可以体现出对这个API的操作
1.api与用户的通信协议为,https。
2. 根据域名就可以判断出哪个是接口哪个是前端:
1. 尽量将api部署在专有域名上。我们发送www.baidu.com,前端会去www.api.baidu.com中拿数据,这样做的目的是为了一眼就能看出这个地址是前端的地址,还是后端的地址,缺点会存在跨域,需要自己解决
2. www.baidu.com/api 这种格式最简单因为不存在跨域
3. 添加版本号
1.可以添加在url上 www.baidu.com/v1
2.还可以加在请求头上
4. url不使用动词而使用名词,推荐复数 www.baidu.com/cats
5.根据method不同做不同的操作。
基于fbv:
urls.py
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^order/', views.order), ]
views.py
def order(request): if request.method == "GET": print("获得订单") elif request.method == "POST": return HttpResponse('生成订单') elif request.method == "put": return HttpResponse('修改订单') elif request.method == "delete": return HttpResponse("删除订单")
基于cbv:
urls.py
urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^order/', views.OrderView.as_view()), ]
views
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('生成订单')
6.通过在url上以传递参数的形式进行过滤。 www.baidu.com/cats?limit=10
7.在返回的信息中,使用的状态码和code用来表示请求是否成功, 其实一般我们后端使用code就可以了
{“code”:200,'msg':操作成功}
200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。 201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。 202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务) 204 NO CONTENT - [DELETE]:用户删除数据成功。 301 永久重定向 302 临时重定向 400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。 401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。 403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。 404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。 406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。 410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。 422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。 500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
8.当发生错误时要返回错误信息
{“code”:2000,'msg':‘删除对象不存在’}
9. Response, 返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范。
1.GET /collection: 返回资源对象的列表(数组) 2.GET /collection/1: 返回单个资源对象 3.POST /collection: 返回新生成的资源对象 4.PUT /collection/1: 返回完整的资源对象 5.PATCH /collection/1: 返回完整的资源对象 6.DELETE /collection/1: 返回一个空值
10.Hypermedia API,RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。为什么要这么做,因为restfull是无状态的,服务端是不能记住你访问了哪里,接下来要访问哪里,只能靠给你发送数据时,添加下一步连接来实现
比如我要访问一个orders列表,它会返回你一个订单列表,这个列表中包含指向每个产品的详细信息的url,这样用户可以根据返回结果得到后续操作需要访问的地址了。
[{ "id": 1, "name": "牛", url: 'www.zoos.com/zoos/1' },{ "id": 2, "name": "羊", url: 'www.zoos.com/zoos/1' }]
一.关于url
- 不用大写;
- 用中杠
-
不用下杠_
; - 参数列表要encode;
- URI使用名词而不是动词,且推荐用复数
- url表示资源的两种方式 资源集合和单个资源
-
#资源集合 /zoos/ #表示所有的动物园 #单个资源 /zoos/1/#表示第一个动物园
6.尽量将api部署在域名后边
https://api.example.com # 错误,会存在跨域问题 https://example.org/api/ #正确
7.避免层级过深的url
#过深的导航容易导致url膨胀,不易维护,如 GET /zoos/1/areas/3/animals/4, #尽量使用查询参数代替路径中的实体导航,如 GET /animals?zoo=1&area=3;
二. 通过标准http方法对资源进行增删改查
1.get 查询 返回 服务器的一个或多个资源
2.post 对单个资源进行添加 返回新增对象
3.put对单个对象进行全部修改,客户端提供完整的更新后的资源 返回更新对象
4.patch对单个对象进行部分修改,客户端提供要更新的那些字段 返回更新对象
5. delete 从服务器中删除资源, 返回空
三. 版本
这里的版本指的是你的应用程序的版本
常见的三种方式:
- 在uri中放版本信息:
GET /v1/users/1
- Accept Header:
Accept: application/json+v1
- 自定义 Header:
X-Api-Version: 1
用第一种,虽然没有那么优雅,但最明显最方便。
四.返回结果
1. Response, 返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范。
1.GET /collection:返回资源对象的列表(数组)
2.GET /collection/resource:返回单个资源对象
3.POST /collection:返回新生成的资源对象
4.PUT /collection/resource:返回完整的资源对象
5.PATCH /collection/resource:返回完整的资源对象
6.DELETE /collection/resource:返回一个空文档
2.在返回的信息中,使用正确的状态码
常见的状态码
200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。 201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。 202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务) 204 NO CONTENT - [DELETE]:用户删除数据成功。
301 永久重定向
302 临时重定向 400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。 401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。 403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。 404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。 406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。 410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。 422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。 500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。 更多看这里:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
3.在返回结果用明确错误的文本(String。注意返回的错误是要给人看的,避免用 1001 这种错误信息),而且适当地加入注释。
1
2
3
|
{ error: "Invalid API key" } |
restfull的特点
下面六条准则定义了一个 REST 系统的特征: 1.客户-服务器(Client-Server),提供服务的服务器和使用服务的客户需要被隔离对待。 2.无状态(Stateless),来自客户的每一个请求必须包含服务器处理该请求所需的所有信息。换句话说,服务器端不能存储来自某个客户的某个请求中的信息,并在该客户的其他请求中使用。
3.可缓存(Cachable),服务器必须让客户知道请求是否可以被缓存。(Ross:更详细解释请参考 理解本真的REST架构风格 以及 StackOverflow 的这个问题 中对缓存的解释。) 4.分层系统(Layered System),服务器和客户之间的通信必须被这样标准化:允许服务器和客户之间的中间层(Ross:代理,网关等)可以代替服务器对客户的请求进行回应,而且这些对客户来说不需要特别支持。 5.统一接口(Uniform Interface),客户和服务器之间通信的方法必须是统一化的。(Ross:GET,POST,PUT.DELETE, etc) 6.支持按需代码(Code-On-Demand,可选),服务器可以提供一些代码或者脚本(Ross:Javascrpt,flash,etc)并在客户的运行环境中执行。这条准则是这些准则中唯一不必必须满足的一条。
(Ross:比如客户可以在客户端下载脚本生成密码访问服务器。)