REST是Representational State Transfer的简称,中文翻译为“表征状态转移”或“表现层状态转化”。
十条RESTful API设计指南
1、数据的安全保障
url一般采用https协议进行传输,可以提高数据交互过程中安全性
2、接口特征表现
使用api关键字标识接口url,代表该url是完成前后台数据交互的
3、多数据版本共存
当一种数据资源有多个版本,应在url中标识数据版本
4、数据即资源
均使用名词复数表示数据资源
5、请求方式决定资源的操作方式
GET :从服务器取出全部资源
GET:后面加数字,从服务器取出单个资源
POST:在服务器新建一个资源
PUT:在服务器更新资源(客户端提供改变后的完整资源)
PATCH:在服务器更新资源(客户端提供改变的属性)
DELETE :从服务器删除资源
6、响应状态码
200:常规请求
201:创建成功
300:永久重定向
301:暂时重定向
403:请求无权限
404:请求路径不存在
405:请求方法不存在
500:服务器异常
7、响应结果
针对不同操作,服务器向用户返回不同的结果
GET:返回资源对象的列表(数组)
GET:后面加数字,返回单个资源对象
POST:返回新生成的资源对象
PUT:返回完整的资源对象
PATCH:返回完整的资源对象
DELETE:返回一个空文档
8、过滤
通过url上传参的形式传递搜索条件
https://api.example.com/v1/zoos?limit=10:指定返回记录的数量
https://api.example.com/v1/zoos?offset=10:指定返回记录的开始位置
https://api.example.com/v1/zoos?page=2&per_page=100:指定第几页,以及每页的记录数
https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序
https://api.example.com/v1/zoos?animal_type_id=1:指定筛选条件
9、错误处理
请求出错时,应返会错误信息
10、Hypermedia API
返回结果中提供链接
基于Django的request进行重新封装,Django的request的属性都可以使用。
对于POST请求、PUT请求的数据通过request.data获取
对于GET请求的参数通过request.query_params获取
根据请求头content-type选择对应的解析器对请求体内容进行处理
JSONParser:仅处理content-type为application/json的请求头
FormParser:仅处理请求头content-type为application/x-www-form-urlencoded 的请求体
MultiPartParser:仅处理请求头content-type为multipart/form-data的请求体
FileUploadParser:仅处理上传的文件
重写类的parser_classes属性
from rest_framework.views import APIView
from rest_framework.parsers import JSONParser, MultiPartParser, FileUploadParser, FormParser
class BookView(APIView):
parser_classes = [JSONParser, MultiPartParser] # 局部使用,重写类的parser_classes属性
def get(self, request):
pass
def post(self, request):
pass
配置settings.py
REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES':[
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser'
]
}
自己封装Response
1.继承Response
2.重写__init__方法
3.调用父类的__init__方法
from rest_framework.response import Response
class ApiResponse(Response):
def __init__(self, code=100, msg='', err='', data=None, status=None, headers=None, **kwargs):
dic = {
'code': code}
if msg:
dic['msg'] = msg
if err:
dic['err'] = err
if data:
dic['data'] = data
dic.update(kwargs)
super().__init__(data=dic, status=status, headers=headers)
默认显示格式:BrowsableAPIRenderer
访问URL方式:
http://127.0.0.1:8000/test/?format=api
http://127.0.0.1:8000/test.api
http://127.0.0.1:8000/test/
显示json格式:JSONRenderer
访问URL方式:
http://127.0.0.1:8000/test/?format=json
http://127.0.0.1:8000/test.json
http://127.0.0.1:8000/test/
显示表格格式:AdminRenderer
访问URL方式:
http://127.0.0.1:8000/test/?format=admin
http://127.0.0.1:8000/test.admin
http://127.0.0.1:8000/test/
显示表单格式:HTMLFormRenderer
访问URL方式:
http://127.0.0.1:8000/test/?format=form
http://127.0.0.1:8000/test.form
http://127.0.0.1:8000/test/
自定义显示模板格式:TemplateHTMLRenderer
重写视图类的renderer_classes属性
from rest_framework.views import APIView
from rest_framework.renderers import HTMLFormRenderer, BrowsableAPIRenderer
class BookView(APIView):
renderer_classes = [HTMLFormRenderer, BrowsableAPIRenderer] # 局部使用,重写类的renderer_classes属性
def get(self, request):
pass
def post(self, request):
pass
配置settings.py
REST_FRAMEWORK = {
'DEFAULT_RENDERER_CLASSES':['rest_framework.renderers.JSONRenderer',
'rest_framework.renderers.BrowsableAPIRenderer']
}
from django.urls import path, re_path
from app01 import views
urlpatterns = [
path('test/', views.TestView.as_view()),
re_path(r'^test/(?P\d+)$' , views.TestView.as_view())
]
传入一个字典{
'请求方式':'视图对应的函数名'}
from django.urls import path, re_path
from app01 import views
urlpatterns = [
path('test/', views.TestView.as_view({
'get': 'list', 'post': 'create'})), # 传入一个字典{'请求方式':'视图对应的函数名'}
re_path(r'test/(?P\d+)$' , views.TestView.as_view({
'get': 'retrieve', 'put': 'update', 'delete': 'destroy'}))
]
1.导入自动生成路由的类
2.实例化
3.注册视图函数
4.拼接路由
# urls
from rest_framework.routers import SimpleRouter, DefaultRouter
from app01 import views
route1 = SimpleRouter() # 实例化
route2 = DefaultRouter()
route1.register('app01/test1', views.TestView) # 注册视图函数,第一个参数为路由地址,第二给参数为视图类
route2.register('app01/test2', views.Test2View)
urlpatterns += route1.urls # 拼接路由,urls为自动生成的路由列表
urlpatterns += route2.urls
action装饰器:函数使用action装饰器装饰后,会自动生成路由
# views.py
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from app01 import models
from utils import ser
class TestView(ModelViewSet):
queryset = models.AgvTestRecord.objects.all()
serializer_class = ser.TestSer
@action(methods=['get'], detail=True, url_path='ccc')
"""
methods:请求方式列表
detail:决定是否带有pk值
当为True时生成的路由:^app01/test1/(?P[^/.]+)/ccc/$ [name='agvtestrecord-action']
当为False时生成的路由:^app01/test1/ccc/$ [name='agvtestrecord-action']
url_path:生成的url路径名,默认为被装饰函数名
url_name:反向解析名,默认为被装饰函数名
"""
def action(self, request, *args, **kwargs):
return Response('OK')
ApiView:基类,继承View
GenericView:基类,继承ApiView
from rest_framework.views import ApiView
from utils.utils import ApiResponse
from app01 import models
from utils import sers
常用类属性:
parser_classes:元组或列表,配置解析器类
renderer_classes:元组或列表,配置渲染器类
authentication_classes:元组或列表,配置认证类
permission_classes:元组或列表,配置权限类
throttle_classes:元组或列表,配置频率类
class TestView(APIView):
def get(self, request, *args, **kwargs):
pk = kwargs.get('pk', None)
if pk:
obj = models.AgvTestRecord.objects.filter(pk=pk).first()
ser_obj = sers.TestSer(obj)
return ApiResponse(code=100, msg='success', data=ser_obj.data)
else:
obj = models.AgvTestRecord.objects.all()
ser_obj = sers.TestSer(obj, many=True)
return ApiResponse(code=100, msg='success'