restful
1:restful
全称是Representational State Transfer
首次出现在2000年Roy Fielding博士论文中。
理解:以网络为基础的应用软件的架构设计,功能强,性能好,适宜通信的架构,
2:RESTful API设计规范
restful 是目前最流行的API设计规范,用于web数据接口的设计。他的最大原则就是容易把握,当细节不容易做对
RESTful的核心思想就是,客户端发出的数据+操作指令都是“动词+宾语”的结构,
比如 GET /articles 这个命令,GET是动词,/articles是宾语,动词通常就有5种HTTP请求方法,对应CRUD操作,
根据 HTTP 规范,动词一律大写。 有些客户端只能使用GET和POST这两种方法。
资源是REST系统的核心概念。 所有的设计都是以资源为中心
(什么是表述性:就是指客户端请求一个资源,服务器拿到的这个资源,就是表述)
资源的地址 在web中就是URL (统一资源标识符)
1、协议(Protocol)
API与用户的通信协议,尽量使用HTTPs协议。
HTTPs协议的所有信息都是加密传播,第三方无法窃听,具有校验机制,一旦被篡改,通信双方会立刻发现,配备身份证书,防止身份被冒充。
2:域名(ROOT URL)应该尽量将API部署在专用域名之下。
3、版本(Versioning)应该将API的版本号放入URL。
https://api.example.com/v1/
另一种做法是,将版本号放在HTTP头信息中,但不如放入URL方便和直观。Github采用这种做法。
注意:
需要注意版本规划,以便以后API的升级和维护。使得API版本变得强制性,不要发布无版本的API,使用简单数字,避免小数点如2.5。
另一种做法是,将版本号放在HTTP头信息中,但不如放入URL方便和直观。Github采用这种做法。
注意:
需要注意版本规划,以便以后API的升级和维护。使得API版本变得强制性,不要发布无版本的API,使用简单数字,避免小数点如2.5。
4 面向资源编程:
路径(Endpoints) 路径表示API的具体网址URL。在RESTful架构中,每个URL代表一种资源(resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与代表的对象名称对应。一般来说,某一同种记录的”集合”(collection),所以API中的名词也应该使用复数。
https://api.example.com/v1/zoos
https://api.example.com/v1/animals
https://api.example.com/v1/employees
具体细则:
1、使用名词而不是动词。举例来说,某个URL是/cards/show/1,其中show是动词,这个URL就设计错了,正确的写法应该是/cards/1,然后用GET方法表示show。如果某些动作是HTTP动词表示不了的,你就应该把动作做成一种资源。比如网上汇款,从账户1向账户2汇款500元,错误的URI是:POST /accounts/1/transfer/500/to/2。正确的写法是把动词transfer改成名词transaction,资源不能是动词,但是可以是一种服务:POST /transaction?from=1&to=2&amount=500.00。
2、使用复数名词。不要混淆名词单数和复数,为了保持简单,只对所有资源使用复数。
举例:
/cars 而不是 /car
/users 而不是 /user
/products 而不是 /product
/settings 而不是 /setting
3、使用子资源表达关系。如果一个资源与另外一个资源有关系,使用子资源。
举例:
GET /cars/911/drivers/ 返回 car 911的所有司机
GET /cars/911/drivers/8 返回 car 911的8号司机
5、method1、使用名词而不是动词。举例来说,某个URL是/cards/show/1,其中show是动词,这个URL就设计错了,正确的写法应该是/cards/1,然后用GET方法表示show。如果某些动作是HTTP动词表示不了的,你就应该把动作做成一种资源。比如网上汇款,从账户1向账户2汇款500元,错误的URI是:POST /accounts/1/transfer/500/to/2。正确的写法是把动词transfer改成名词transaction,资源不能是动词,但是可以是一种服务:POST /transaction?from=1&to=2&amount=500.00。
2、使用复数名词。不要混淆名词单数和复数,为了保持简单,只对所有资源使用复数。
举例:
/cars 而不是 /car
/users 而不是 /user
/products 而不是 /product
/settings 而不是 /setting
3、使用子资源表达关系。如果一个资源与另外一个资源有关系,使用子资源。
举例:
GET /cars/911/drivers/ 返回 car 911的所有司机
GET /cars/911/drivers/8 返回 car 911的8号司机
GET (查询数据) #从服务器取出资源
POST(创建数据)#在服务器更新资源
PUT(修改数据)#在服务器更新资源
PATCH(修改属性)#在服务器更新资源
delete(删除数据)#从服务器删除数据
6、过滤信息(Filtering)
如果记录数量很多,服务器不可能都将它们返回给用户。API应该提供参数,过滤返回结果。为集合提供过滤、排序、选择和分页等功能。
下面是一些常见的参数。
https://api.example.com/v1/zoos
- ?limit=10:指定返回记录的数量
- ?offset=10:指定返回记录的开始位置。
- ?pageNumber=2&perSize=100:指定第几页,以及每页的记录数。
- ?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
- ?animal_type_id=1:指定筛选条件
7、状态码(Status Codes)
服务器向用户返回的状态码和提示信息,常见的有以下一些(方括号中是该状态码对应的HTTP动词)。
- 200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。******
- 201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。*******
- 202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
- 204 NO CONTENT - [DELETE]:用户删除数据成功。
- 301 NO CONTENT -永久重定项*******
- 302 NO CONTENT -临时重定项*******
- 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 - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
3.APIView使用
来源
from rest_framework.views import APIView
from rest_framework.response import Response
获取参数
get
data = request.query_params
post
data = request.data
*序列化器
class ClassroomSer(serializers.Serializer):
class_name = serializers.CharField(max_length=20,required=True,label="班级名称")
address= serializers.CharField(max_length=40,label="地址")
#创建
def create(self, validated_data):
return demomodel.Classroom.objects.create(**validated_data)
#修改
def update(self, instance, validated_data):
instance.class_name = validated_data.get("class_name",instance.class_name)
instance.address = validated_data.get("address",instance.address)
instance.save()
return instance
#验证单⼀字段
# def validate_address(self, attrs):
# if attrs != "河南":
# raise serializers.ValidationError("教室不在河南")
# return attrs
#验证全部数据
def validate(self, attrs):
if attrs.get("address") != "河南":
raise serializers.ValidationError("教室不在河南")
return attrs