rest-framework之url控制、解析器、版本控制、响应器、分页器

一、url控制

1.1、自定义(原始)

路由一般写法如下

FBV:

url(r'^site/', views.site),
url(r'^site/(?P<name>\w+)/', views.site)

CBV:

from django.conf.urls import url
from app01 import views
urlpatterns = [
    url(r'^books/$', views.BookView.as_view()),
    url(r'^books/(?P<pk>\d+)$', views.BookDetailView.as_view()),
]

1.2、继承了ModelViewSet的视图的路由写法

本质是继承了ViewSetMixin,这个类重写了as_view()方法

路由 :

from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^publish/$', views.PublishView.as_view({'get': 'list', 'post': 'create'})),
    url(r'^publish/(?P<pk>\d+)/', views.PublishView.as_view({
        'get': 'retrieve', 'delete': 'destroy', 'put': 'update'
    }))
]

序列化

from rest_framework.serializers import ModelSerializer
from app01 import models
class PublishSerializers(ModelSerializer):
    class Meta:
        model = models.Publish
        fields = '__all__'

视图

from rest_framework.viewsets import ModelViewSet
from app01 import models
from app01.serializer import PublishSerializers
class PublishView(ModelViewSet):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializers

1.3、自动生成路由(必须继承ModelViewSet类)

生成路由需要导入SimpleRouter,DefaultRouter两个类

  • SimpleRouter 自动生成两条路由
  • DefaultRouter自动生成四条路由

路由: 

from django.conf.urls import url, include
from django.contrib import admin
from app01 import views
from rest_framework.routers import SimpleRouter, DefaultRouter
router = SimpleRouter()
router.register('publish', views.PublishView)

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'', include(router.urls))
    ]

可以通过如下方式访问(指定format=json拿到的就是json格式的数据):

http://127.0.0.1:8000/publish/?format=json

http://127.0.0.1:8000/publish/1/?format=json

http://127.0.0.1:8000/publish/

http://127.0.0.1:8000/publish/1/

 视图:与第二种的一样,只是路由是自己生成

from rest_framework.viewsets import ModelViewSet
from app01 import models
from app01.serializer import PublishSerializers
class PublishView(ModelViewSet):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializers

如果用DefaultRouter生成路由,可以直接点访问(直接拿到的就是json格式的数据,而不是页面):

http://127.0.0.1:8000/publish/1.json

http://127.0.0.1:8000/publish.json

 二、解析器

根据请求头 content-type 选择对应的解析器对请求体内容进行处理。

有application/json,x-www-form-urlencoded,form-data等格式。

一般不需要改动,项目最开始全局配置一下就行了,作用是控制视图类能够解析前端传过来的格式是什么样的。

三种编码格式:urlencoded,formdata,json
    -urlencoded:在body体中的格式是:name=lqz&age=18&wife=liuyifei
    -formdata:在body体中的格式数据部分跟文件部分有区分
    -json格式:在body体中就是json格式 

 2.1、全局使用

在settings配置文件中配置即可全局使用

REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES':[
        'rest_framework.parsers.JSONParser'  # 对应application/json
        'rest_framework.parsers.FormParser'   # 对应application/x-www-form-urlencoded
        'rest_framework.parsers.MultiPartParser'  # 对应multipart/form-data
    ]

}

路由 

url(r'^test/', views.Test.as_view())

 视图

from rest_framework.views import APIView
from rest_framework.response import Response
class Test(APIView):
    def post(self, request, *args, **kwargs):
        print(request.content_type)
        # 获取请求的值,并使用对应的parser进行处理
        print(request.data)
        # 格式为application/json或x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)
        return Response('post响应内容')

    def put(self, request, *args, **kwargs):
        return Response('put响应内容')

2.2、局部使用

  • from rest_framework.parsers import JSONParser, FormParser, MultiPartParser
    
  • parser_classes = [JSONParser,]
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser
class Test(APIView):
    parser_classes = [JSONParser,]  # 除了json格式,发其他的request.POST都为空
    def post(self, request, *args, **kwargs):
        print(request.content_type)
        # 获取请求的值,并使用对应的parser进行处理
        print(request.data)
        # 格式为application/json或x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)
        return Response('post响应内容')

    def put(self, request, *args, **kwargs):
        return Response('put响应内容')

2.3、源码分析

在调用request.data时,才开始解析。

查看self._load_data_and_files()方法,看见这句代码:self._data, self._files = self._parse(),到parse里面看看

查看self.negotiator.select_parser(self, self.parsers)

最终调用parser的解析方法来解析parsed = parser.parse(stream, media_type, self.parser_context)

 三、响应器

3.1、作用

根据 用户请求URL 或 用户可接受的类型,筛选出合适的 渲染组件。这个一般不用改,全局配置即可
用户请求URL:
    http://127.0.0.1:8000/test/?format=json
    http://127.0.0.1:8000/test.json

3.2、 内置渲染器

显示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/

默认显示格式:BrowsableAPIRenderer(可以修改它的html文件)

访问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/

表格方式: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/

form表单方式: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/

3.3、全局使用

REST_FRAMEWORK = {
    'DEFAULT_RENDERER_CLASSES':['rest_framework.renderers.JSONRenderer']
}

3.4、局部使用

在视图类中配置即可

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.renderers import AdminRenderer,JSONRenderer,BrowsableAPIRenderer
class Test(APIView):
    renderer_classes = [JSONRenderer, BrowsableAPIRenderer]
    def get(self, request, *args, **kwargs):
        return Response('get响应内容')

注意:如果同时多个存在时,自动根据URL后缀来选择渲染器。

http://127.0.0.1:8000/test/?format=api   ——网页

http://127.0.0.1:8000/test/?format=json   ——json格式

 四、版本控制

4.1、内置的版本控制类

from rest_framework.versioning import QueryParameterVersioning,AcceptHeaderVersioning,NamespaceVersioning,URLPathVersioning

# 基于url的get传参方式:QueryParameterVersioning------>如:/users?version=v1
# 基于url的正则方式:URLPathVersioning------>/v1/users/
# 基于 accept 请求头方式:AcceptHeaderVersioning------>Accept: application/json; version=1.0
# 基于主机名方法:HostNameVersioning------>v1.example.com
# 基于django路由系统的namespace:NamespaceVersioning------>example.com/v1/users/

4.2、局部使用

注意:版本控制的局部使用不是列表传多个,而是只能有一种方法控制

# 在CBV类中加入
versioning_class = URLPathVersioning

路由:

url(r'^(?P<version>[v1|v2]+)/test/', views.Test.as_view()),

视图: 

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.versioning import URLPathVersioning
class Test(APIView):
    versioning_class = URLPathVersioning
    def get(self, request, *args, **kwargs):
        if request.version == 'v1':
            return Response('V1版本的代码')
        return Response('V2版本的代码')

 访问http://127.0.0.1:8000/v1/test/,根据对应的版本,做出不同的响应。

4.3、全局使用

REST_FRAMEWORK = {
    'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning',
    'DEFAULT_VERSION': 'v1',            # 默认版本(从request对象里取不到,显示的默认值)
    'ALLOWED_VERSIONS': ['v1', 'v2'],   # 允许的版本
    'VERSION_PARAM': 'version'          # URL中获取值的key
}

4.4、源码分析

首先是走的APIView类的as_view()方法,然后到他的dispatch()方法,再进入到self.initial()方法,可以看到它内部有下面的版本控制的代码

我们找找APIView的determine_version方法看看

我配的是这个URLPathVersioning类(先看我自己配置的,如果没有就去配置文件找),给它加括号实例化,调用自己的determine_version方法:

执行完上面的步骤又回到了APIView的determine_version方法,然后执行完将结果返回给self.initial()方法

 

五、分页器

先来准备点数据

models.py

from django.db import models

class Publish(models.Model):
    name=models.CharField(max_length=32)
    city=models.CharField(max_length=64)

批量插入

# 批量插入数据
def insert():
    ls = []
    for i in range(100):
        ls.append(models.Publish(name='%s出版社' % i, city='%s城市' % i))
    models.Publish.objects.bulk_create(ls)

序列化数据

from rest_framework.serializers import ModelSerializer
from app01 import models
class PublishSerializers(ModelSerializer):
    class Meta:
        model = models.Publish
        fields = '__all__'

 5.1、常规分页

视图:分页(查看第n页,每页显示n条

from app01.serializer import PublishSerializers
from app01 import models
from rest_framework.views import APIView
from rest_framework.pagination import PageNumberPagination

class PublishView(APIView):
    def get(self, request, *args, **kwargs):
        # 查询所有数据
        res = models.Publish.objects.all()
        # 实例化产生一个普通分页对象
        page = PageNumberPagination()
        # 指定每页显示多少条
        page.page_size = 10
        # 指定查询哪一页的key值
        page.page_query_param = 'xxx'
        # 前端控制每页显示多少条的查询key值比如size=9,表示一页显示9条
        page.page_size_query_param = 'size'
        # 控制每页最大显示多少,size如果传100,最多也是显示指定的条数
        page.max_page_size = 10
        res_page = page.paginate_queryset(res, request, self)
        # 序列化
        pub_ser = PublishSerializers(instance=res_page, many=True)
        # 去settings中配置每页显示多少条:'PAGE_SIZE':2   #表示每页显示两条
        # return Response(pub_ser.data)
        # 返回的结果中带了总条数,上一页下一页的链接
        return page.get_paginated_response(pub_ser.data)

在配置文件中配置每页显示多少条,其实我们在视图里已经写了,配置文件的配不配都行

REST_FRAMEWORK = {
    # "DEFAULT_PARSER_CLASSES":[
    #     'rest_framework.parsers.JSONParser',
    # ],
    'PAGE_SIZE': 10   # 表示每页显示十条
}

路由:

url(r'^publish/', views.PublishView.as_view())

5.2、偏移分页(在第n个位置,向后查看n条数据)

from app01.serializer import PublishSerializers
from app01 import models
from rest_framework.views import APIView
from rest_framework.pagination import LimitOffsetPagination

class PublishView(APIView):
    def get(self, request, *args, **kwargs):
        res = models.Publish.objects.all()
        # 实例化一个偏移分页对象
        page = LimitOffsetPagination()
        """四个参数"""
        # 从标杆位置往后取几个,默认取三个,可以指定
        page.default_limit = 3
        # 每次取的条数
        page.limit_query_param = 'limit'
        # 标杆值,现在偏移到哪个位置,如果offset=6,表示当前在第6条位置上,往后取limit=多少条
        page.offset_query_param = 'offset'
        # 最大取10条
        page.max_limit = 10
        res_page = page.paginate_queryset(res, request, self)
        # 序列化
        pub_ser = PublishSerializers(res_page, many=True)
        """到settings配置每页显示多少条"""
        return page.get_paginated_response(pub_ser.data)

5.3、cursor游标方式分页

只能看上一页和下一页,速度快

from app01.serializer import PublishSerializers
from app01 import models
from rest_framework.views import APIView
from rest_framework.pagination import CursorPagination

class PublishView(APIView):
    def get(self, request, *args, **kwargs):
        res = models.Publish.objects.all()
        # 实例化产生一个游标分页对象
        page = CursorPagination()
        """三个参数"""
        # 每页显示的大小
        page.page_size = 3
        # 查询的key值
        page.cursor_query_param = 'cursor'
        # 按什么排序
        page.ordering = 'id'

        res_page = page.paginate_queryset(res, request, self)
        # 序列化
        pub_ser = PublishSerializers(instance=res_page, many=True)
        """到settings配置每页显示多少条,可配可不配"""
        # return Response(pub_ser.data)
        return page.get_paginated_response(pub_ser.data)

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值