RESTful规范
编程是数据结构和算法的结合,而在Web类型的App中,我们对于数据的操作请求是通过url来承载的,本文详细介绍了REST规范和CBV请求流程。
编程是数据结构和算法的结合,小程序如简单的计算器,我们输入初始数据,经过计算,得到最终的数据,这个过程中,初始数据和结果数据都是数据,而计算过程是我们所说的广义上的算法。
大程序,如一个智能扫地机器人,我们可以设置打扫的距离,左右摆动的幅度来打扫房间,这里面打扫的举例,摆动幅度,都是数据,而打扫的过程是较为复杂的算法过程,总之,也是算法,即程序的实现方式。
另外,我们还可以设置打扫时间等等初始数据。
总之一句话,编程即数据结构和算法的结合。简单的程序可能不需要跟用户交互数据,但是现代的应用程序几乎都需要跟用户进行交互,不分应用程序类型,不管是CS型还是BS型的程序都是如此,而Python最擅长的Web App即BS型的程序,就是通过url和http来跟用户进行数据交互的,通过url和http请求,用户可以操作服务器端的程序,主要操作分为:增、删、改、查几类。
引入
在开始之前,我们回顾一下咱们之前写过的图书管理系统项目,请仔细回想一下,对于该项目的设计,我们大概是以下面这种方式来实现的
传统url设计风格
- url各式各样,设计混乱
理论上来说,这种方式完全可以实现我们的需求,但是一旦项目丰富起来,随着数据量增加,随着各个业务系统之间的逻辑关系不断的复杂,url会越来越复杂,理论上来说,不管是什么类型、什么名称的url都能指向具体的业务逻辑(视图函数),从而实现业务需求,但是如果没有明确的规范,因每个人的思维方式不一样、命名方式不一样而导致的url非常的乱,不方便项目的后期维护和扩展。
- 对于请求处理成功或者失败的返回信息没有明确的响应信息规范,返回给客户端的信息往往都是很随意的
以上这些情况的出现,导致了很多的问题,让互联网的世界变得杂乱不堪,日益复杂且臃肿。因此http协议创始人警告我们这些凡人们正在错误的使用http协议,除了警告,他还发表了一篇博客,大概意思就是教大家如何正确使用http协议,如何正确定义url,这就是REST(Representational State Transfer),不需要管这几个英文单词代表什么意思,只需要记住下面一句话:
- 用url唯一定位资源,用Http请求方式(GET, POST, DELETE, PUT)描述用户行为
根据这句话,我们重新定义图书管理系统中的url
RESTful Api设计风格
可以看到,url非常简洁优雅,不包含任何操作,不包含任何动词,简简单单,用来描述服务器中的资源而已,服务器根据用户的请求方式对资源进行各种操作。而对数据的操作,最常见的就是CRUD(创建,读取,更新,删除),通过不同的请求方式,就足够描述这些操作方式了。如果不够用,Http还有其他的请求方式呢!比如:PATCH,OPTIONS,HEAD, TRACE, CONNECT。
REST定义返回结果
每一种请求方式的返回结果不同。
REST定义错误信息
{
"error": "Invalid API key"
}
通过一个字典,返回错误信息。
这就是REST,上图中的url就是根据REST规范进行设计的RESTful api。
概念
REST是一种软件架构设计风格,不是标准,也不是具体的技术实现,只是提供了一组设计原则和约束条件。是目前最流行的 API 设计规范,用于 Web 数据接口的设计。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存等机制。2000年,由Roy Fielding在他的博士论文中提出,Roy Fielding是HTTP规范的主要编写者之一。
URL规范
1.不用大写;
2.用中杠 - 不用下杠 _ ;
3.参数列表要encode;
4.URI中的名词表示资源集合,使用复数形式。
5.在RESTful架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词(特殊情况可以使用动词),而且所用的名词往往与数据库的表格名对应。
restful 规范
1. 根据method不同,进行不同操作
GET/POST/PUT/DELETE/PATCH
2. 面向资源编程
http://www.nnblog.com/blog
3. 体现版本
http://www.nnblog.com/v1/blog
http://www.nnblog.com/v2/blog
https://v4.bootcss.com/
https://v3.bootcss.com/
4. 体现是API
http://www.nnblog.com/api/v1/blog
http://www.nnblog.com/api/v2/blog
http://api.nnblog.com/v1/salary
http://api.luffycity.com/v2/blog
5. https
https://www.nnblog.com/api/v1/blog
https://www.nnblog.com/api/v2/blog
6. 响应式设置状态码
200
300
400
500
return HttpResponse('adfasdf',status=300)
7. 条件
https://www.nnblog.com/api/v2/blog?page=1&size=10
8. 返回值
https://www.nnblog.com/api/v2/salary
GET: 所有列表
{
code: 10000,
data: [
{'id':1,'title':'a'},
{'id':1,'title':'b'},
{'id':1,'title':'c'},
]
}
POST: 返回新增的数据
{'id':1,'title':'高亮'}
https://www.nnblog.com/api/v2/salary/1/
GET: 获取单条数据
{'id':1,'title':'d'}
PUT:更新
{'id':1,'title':'e'}
PATCH: 局部更新
{'id':1,'title':'f'}
DELETE:删除
9. 返回错误信息
{
code: 100001,
error: 'xxx错误'
}
10. Hypermedia API
ret = {
code: 1000,
data:{
id:1,
name:'jiumo',
depart_id:http://www.nnblog.com/api/v1/blog/8/
}
}
Request
url唯一定位资源(数据),http请求方式描述用户行为
GET 127.0.0.1:8000/books/ # 获取所有数据
POST 127.0.0.1:8000/books/ # 添加一条数据
PUT 127.0.0.1:8000/books/{id} # 修改一条数据
DELETE 127.0.0.1:8000/books/{id} # 删除一条数据
GET 127.0.0.1:8000/books/{id} # 获取单条数据
Response
返回数据规范
GET 127.0.0.1:8000/books/ # 获取所有数据 [ {}, {}, {}]
POST 127.0.0.1:8000/books/ # 添加一条数据 {}
PUT 127.0.0.1:8000/books/{id} # 修改一条数据 {}
DELETE 127.0.0.1:8000/books/{id} # 删除一条数据 ""
GET 127.0.0.1:8000/books/{id} # 获取单条数据 {}
错误信息
{ "error": "error_message" }
状态码
服务器向用户返回的状态码和提示信息,常见的有以下一些(方括号中是该状态码对应的HTTP动词):
200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。
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 - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
URI失效:
随着系统发展,总有一些API失效或者迁移,对失效的API,返回404 not found 或 410 gone;对迁移的API,返回 301重定向。
那么,Django RestFramework与rest有什么关系呢?
其实,DRF(Django RestFramework)是一套基于Django开发的、帮助我们更好的设计符合REST规范的Web应用的一个Django App,所以,本质上,它是一个Django App。