Django REST framework 个人小解

1,认识RESTful

在前后端分离模式,后端API接口如何定义?

  • 后端数据库中保存了商品的信息,前端可能需要对商品数据进行增删改查,那相应的每个操作后端都需要提供一个API接口:
  • POST/add-goods 增加商品
  • POST /delete-goods 删除商品
  • POST /update-goods 修改商品
  • GET /get-goods 查询商品信息
  • 普遍采用的API的RESTful设计风格

REST

  • 即Representational State Transfer的缩写。维基百科称其为“具象状态传输”,国内大部分人理解为“表现层状态转化”。

  • RESTful是一种开发理念。维基百科说:REST是设计风格而不是标准。 REST描述的是在网络中client和server的一种交互形式;REST本身不实用,实用的是如何设计 RESTful API(REST风格的网络接口),一种万维网软件架构风格。

  • REST特点:url简洁,将参数通过url传到服务器

  • 综合上面的解释,RESTful架构就是:

    • 每一个URL代表一种资源;
    • 客户端和服务器之间,传递这种资源的某种表现层;
    • 客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"。

2,RESTful设计方法

  • (1) 域名

  • 应该尽量将API部署在专用域名之下。

  • https://api.example.com

  • 如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下。

  • https://example.org/api/

  • (2) 版本(Versioning)

    • 应该将API的版本号放入URL。 http://www.example.com/app/1.0/foo
    • 另一种做法是,将版本号放在HTTP头信息中,但不如放入URL方便和直观 Accept: vnd.example-com.foo+json; version=1.0
  • (3) 路径

  • 资源作为网址,只能有名词,不能有动词,而且所用的名词往往与数据库的表名对应。

    • /getProducts/listOrders/retreiveClientByOrder?orderId=1
  • 对于一个简洁结构,你应该始终用名词。 此外,利用的HTTP方法可以分离网址中的资源名称的操作

GET /products :将返回所有产品清单
POST /products :将产品新建到集合
GET /products/4 :将获取产品 4
PATCH(或)PUT /products/4 :将更新产品 4  
  • API中的名词应该使用复数。无论子资源或者所有资源
  • 举例来说,获取产品的API可以这样定义
获取单个产品:http://127.0.0.1:8080/AppName/rest/products/1
获取所有产品: http://127.0.0.1:8080/AppName/rest/products
  • (4) HTTP动词
    • 对于资源的具体操作类型,由HTTP动词表示。

    • 常用的HTTP动词有下面四个(括号里是对应的SQL命令)。

  GET(SELECT):从服务器取出资源(一项或多项)。
  POST(CREATE):在服务器新建一个资源。
  PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
  DELETE(DELETE):从服务器删除资源。
# 例如
GET /zoos:列出所有动物园
POST /zoos:新建一个动物园(上传文件)
GET /zoos/ID:获取某个指定动物园的信息
PUT /zoos/ID:更新某个指定动物园的信息(提供该动物园的全部信息)
PATCH /zoos/ID:更新某个指定动物园的信息(提供该动物园的部分信息)
DELETE /zoos/ID:删除某个动物园
GET /zoos/ID/animals:列出某个指定动物园的所有动物
DELETE /zoos/ID/animals/ID:删除某个指定动物园的指定动物

3,使用Django开发REST 接口

  • 在Django框架中使用的图书英雄案例来写一套支持图书数据增删改查的REST API接口,来理解REST API的开发
# views.py

from datetime import datetime

class BooksAPIVIew(View):
    """
    查询所有图书、增加图书
    """
    def get(self, request):
        """
        查询所有图书
        路由:GET /books/
        """
        queryset = BookInfo.objects.all()
        book_list = []
        for book in queryset:
            book_list.append({
                'id': book.id,
                'btitle': book.btitle,
                'bpub_date': book.bpub_date,
                'bread': book.bread,
                'bcomment': book.bcomment,
                'image': book.image.url if book.image else ''
            })
        return JsonResponse(book_list, safe=False)

4,明确REST接口开发的核心任务

  • 将程序中的一个数据类型转换为其他格式(字典,json,XML等),例如将Django中模型类对象转换为json字符串,这个转换过程称为序列化
queryset = BookInfo.objects.all()
book_list = []
# 序列化
for book in queryset:
    book_list.append({
        'id': book.id,
        'btitle': book.btitle,
        'bpub_date': book.bpub_date,
        'bread': book.bread,
        'bcomment': book.bcomment,
        'image': book.image.url if book.image else ''
    })
return JsonResponse(book_list, safe=False)
  • 反之,将其他格式转换为程序中的数据,例如将json字符串转换为Django中的模型类对象,这个过程称为反序列化
json_bytes = request.body
json_str = json_bytes.decode()

# 反序列化
book_dict = json.loads(json_str)
book = BookInfo.objects.create(
    btitle=book_dict.get('btitle'),
    bpub_date=datetime.strptime(book_dict.get('bpub_date'), '%Y-%m-%d').date()
)
  • 在开发REST API时,视图中要频繁的进行序列化与反序列化的编写
  • 在开发 REST API接口时,视图中需要做的核心的事是:
    • 将数据库序列化为前端所需要的格式,并返回
    • 将前端发动的数据反序列化为数据模型对象 ,并保存到数据库中

5,REST framework Request 与 Response

1. Request

常用属性
  • .data
    - reuest.data返回解析之后的请求数据,类似于Django中标准的request.POSTrequest.FILES属性
    - 包含了解析之后的文件和非文件数据
    - 包含了对POST、PUT、PATCH请求解析后的数据
    - 利用了REST frameworkparses解析器,不仅支持表单类型数据,也支持JSON数据
  • .query_params
    • request.query_params与Django标准的request.GET相同,只是换了名字

2,Response

rest_framework.response.Response
  • REST framework提供了一个响应类Response,使用该类构造响应对象时,响应的具体数据内容会被转换(render渲染)成符合前端需求的类型
  • REST framework提供了Renderer 渲染器,用来根据请求头中的Accept(接收数据类型声明)来自动转换响应数据到对应格式。如果前端请求中未进行Accept声明,则会采用默认方式处理响应数据,我们可以通过配置来修改默认响应格式。
REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES': (  # 默认响应渲染类
        'rest_framework.renderers.JSONRenderer',  # json渲染器
        'rest_framework.renderers.BrowsableAPIRenderer',  # 浏览API渲染器
    )
}
构造方式
Response(data, status=None, template_name=None, headers=None, content_type=None)

6,视图

REST framework 提供了众多的通用视图基类与扩展类,以简化视图的编写。

1. 两个基类

1)APIView rest_framework.views.APIView
  • APIView是REST framework提供的所有视图的基类,继承自Django的View父类。
  • APIViewView的不同之处在于:
    • 传入到视图方法中的是REST framework的Request对象,而不是Django的HttpRequeset对象;
    • 视图方法可以返回REST framework的Response对象,视图会为响应数据设置(render)符合前端要求的格式;
    • 任何APIException异常都会被捕获到,并且处理成合适的响应信息;
    • 在进行dispatch()分发前,会对请求进行身份认证、权限检查、流量控制。
2)GenericAPIView rest_framework.generics.GenericAPIView
  • 继承自APIVIew,增加了对于列表视图和详情视图可能用到的通用支持方法。通常使用时,可搭配一个或多个Mixin扩展类。

2. 五个扩展类

1)ListModelMixin
  • 列表视图扩展类,提供list(request, *args, **kwargs)方法快速实现列表视图,返回200状态码。

  • 该Mixin的list方法会对数据进行过滤和分页。

2)CreateModelMixin
  • 创建视图扩展类,提供create(request, *args, **kwargs)方法快速实现创建资源的视图,成功返回201状态码。
  • 如果序列化器对前端发送的数据验证失败,返回400错误。
3) RetrieveModelMixin
  • 详情视图扩展类,提供retrieve(request, *args, **kwargs)方法,可以快速实现返回一个存在的数据对象。
  • 如果存在,返回200, 否则返回404。
4)UpdateModelMixin
  • 更新视图扩展类,提供update(request, *args, **kwargs)方法,可以快速实现更新一个存在的数据对象。
  • 同时也提供partial_update(request, *args, **kwargs)方法,可以实现局部更新。
  • 成功返回200,序列化器校验数据失败时,返回400错误。
5)DestroyModelMixin
  • 删除视图扩展类,提供destroy(request, *args, **kwargs)方法,可以快速实现删除一个存在的数据对象。
  • 成功返回204,不存在返回404。

3. 几个可用子类视图

1) CreateAPIView
  • 提供 post 方法
  • 继承自: GenericAPIView、CreateModelMixin
2)ListAPIView
  • 提供 get 方法
  • 继承自:GenericAPIView、ListModelMixin
3)RetireveAPIView
  • 提供 get 方法
  • 继承自: GenericAPIView、RetrieveModelMixin
4)DestoryAPIView
  • 提供 delete 方法
  • 继承自:GenericAPIView、DestoryModelMixin
5)UpdateAPIView
  • 提供 put 和 patch 方法
  • 继承自:GenericAPIView、UpdateModelMixin
6)RetrieveUpdateAPIView
  • 提供 get、put、patch方法
7)RetrieveUpdateDestoryAPIView
  • 提供 get、put、patch、delete方法
  • 继承自:GenericAPIView、RetrieveModelMixin、UpdateModelMixin、DestoryModelMixin

4. 视图集ViewSet

使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中:
  • list() 提供一组数据

  • retrieve() 提供单个数据

  • create() 创建数据

  • update() 保存数据

  • destory() 删除数据

  • ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等。

  • 视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上。如:

class BookInfoViewSet(viewsets.ViewSet):

    def list(self, request):
        ...

    def retrieve(self, request, pk=None):
        ...
  • 在设置路由时,我们可以如下操作
urlpatterns = [
    url(r'^books/$', BookInfoViewSet.as_view({'get':'list'}),
    url(r'^books/(?P<pk>\d+)/$', BookInfoViewSet.as_view({'get': 'retrieve'})
]
action属性
  • 在视图集中,我们可以通过action对象属性来获取当前请求视图集时的action动作是哪个。

  • 例如:

def get_serializer_class(self):
    if self.action == 'create':
        return OrderCommitSerializer
    else:
        return OrderDataSerializer

常用视图集父类

1) ViewSet
  • 继承自APIView,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等。

  • 在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法。

2)GenericViewSet
  • 继承自GenericAPIView,作用也与GenericAPIVIew类似,提供了get_object、get_queryset等方法便于列表视图与详情信息视图的开发。
3)ModelViewSet
  • 继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin。
4)ReadOnlyModelViewSet
  • 继承自GenericAPIVIew,同时包括了ListModelMixin、RetrieveModelMixin。

路由Routers

  • 对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息。

  • REST framework提供了两个router

    SimpleRouter
    DefaultRouter

7,其他功能

认证Authentication

  • 认证失败会有两种可能的返回值:

    • 401 Unauthorized 未认证
    • 403 Permission Denied 权限被禁止

权限Permissions

  • 权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。

    • 在执行视图的dispatch()方法前,会先进行视图访问权限的判断
    • 在通过get_object()获取具体对象时,会进行对象访问权限的判断

限流Throttling

  • 可以对接口访问的频次进行限制,以减轻服务器压力。

过滤Filtering

  • 对于列表数据可能需要根据字段进行过滤,我们可以通过添加django-fitlter扩展来增强支持。

  • pip insall django-filter

排序

  • 对于列表数据,REST framework提供了OrderingFilter过滤器来帮助我们快速指明数据按照指定字段进行排序。

分页Pagination

  • REST framework提供了分页的支持。

版本Versioning

  • REST framework提供了版本号的支持。
  • 在需要获取请求的版本号时,可以通过request.version来获取。
  • 默认版本功能未开启,request.version 返回None。
  • 开启版本支持功能,需要在配置文件中设置DEFAULT_VERSIONING_CLASS

异常处理 Exceptions

  • REST framework提供了异常处理,可以自定义异常处理函数。

  • REST framework定义的异常

    • APIException 所有异常的父类
    • ParseError 解析错误
    • AuthenticationFailed 认证失败
    • NotAuthenticated 尚未认证
    • PermissionDenied 权限决绝
    • NotFound 未找到
    • MethodNotAllowed 请求方式不支持
    • NotAcceptable 要获取的数据格式不支持
    • Throttled 超过限流次数
    • ValidationError 校验失败

自动生成接口文档

  • REST framework可以自动帮助我们生成接口文档。

  • 接口文档以网页的方式呈现。

  • 自动接口文档能生成的是继承自APIView及其子类的视图。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值