DRF url控制 解析器 响应器 版本控制 分页(常规分页,偏移分页,cursor游标分页)

url控制

第二种写法(只要继承了ViewSetMixin)

     url(r‘^pub/$‘,views.Pub.as_view({‘get‘:‘list‘,‘post‘:‘create‘})), #获取所有记得路由后面加$结束符  #pub/?format=json
     url(r‘^pub\.(?P<format>\w+)$‘,views.Pub.as_view({‘get‘:‘list‘,‘post‘:‘create‘})),       #pub.json
     url(r‘^pub/(?P<pk>\d+)$‘,views.Pub.as_view({‘get‘:‘retrieve‘,‘put‘:‘update‘,‘delete‘:‘destroy‘})),   #获取一条

第三种(自动生成路由,必须继承ModelViewSet)

from django.conf.urls import url,include

  SimpleRouter 自动生成两条路由

from rest_framework.routers import SimpleRouter,DefaultRouter #路由控制

router = SimpleRouter()
router.register(‘pub‘,views.Pub)

urlpatterns = [
    url(r‘^admin/‘, admin.site.urls),
    #其他路由

    url(r‘‘,include(router.urls)),]

  DefaultRouter自动生成四条路由

from rest_framework.routers import SimpleRouter,DefaultRouter #路由控制

router = DefaultRouter()
router.register(‘pub‘,views.Pub)

urlpatterns = [
    url(r‘^admin/‘, admin.site.urls),
    #其他路由
    url(r‘‘,include(router.urls)),]
解析器(一般不需要动,项目最开始全局配置一下就可以了)

作用:控制视图类能够解析前端传过来的格式是什么样的 (默认配置三种都有) 有application/json,x-www-form-urlencoded,form-data等格式

全局使用:在settings中配置:

REST_FRAMEWORK = {
                    "DEFAULT_PARSER_CLASSES":[
                        ‘rest_framework.parsers.JSONParser‘,]
}

局部使用:

from rest_framework.parsers import JSONParser,FormParser,MultiPartParser,FileUploadParser
                                    #json字典 urlencoded  form-data       文件

  在视图类中

parser_classes=[JSONParser,]

源码流程

  当调用request.data的时候去执行解析方法

-->根据传过来的编码方式选择一个解析器对象

--->调用解析器对象的parser方法完成解析

在调用request.data时,才进行解析,由此入手
    @property
    def data(self):
        if not _hasattr(self, ‘_full_data‘):
            self._load_data_and_files()
        return self._full_data
查看self._load_data_and_files()方法---->self._data, self._files = self._parse()

        def _parse(self):
            #用户请求头里content_type的值
            media_type = self.content_type

            #self.parsers 就是用户配置的parser_classes = [FileUploadParser,FormParser ]
            #self里就有content_type,传入此函数
            parser = self.negotiator.select_parser(self, self.parsers)
查看self.negotiator.select_parser(self, self.parsers)
     def select_parser(self, request, parsers):
        #同过media_type和request.content_type比较,来返回解析器,然后调用解析器的解析方法
        #每个解析器都有media_type = ‘multipart/form-data‘属性
        for parser in parsers:
            if media_type_matches(parser.media_type, request.content_type):
                return parser
        return None
最终调用parser的解析方法来解析parsed = parser.parse(stream, media_type, self.parser_context)

源码注释

Request实例化,parsers=self.get_parsers()
    Request(
                request,
                parsers=self.get_parsers(),
                authenticators=self.get_authenticators(),
                negotiator=self.get_content_negotiator(),
                parser_context=parser_context
            )
get_parsers方法,循环实例化出self.parser_classes中类对象
    def get_parsers(self):
        return [parser() for parser in self.parser_classes]
self.parser_classes 先从类本身找,找不到去父类找即APIVIew 中的
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
api_settings是一个对象,对象里找DEFAULT_PARSER_CLASSES属性,找不到,会到getattr方法
        def __getattr__(self, attr):
            if attr not in self.defaults:
                raise AttributeError("Invalid API setting: ‘%s‘" % attr)

            try:
                #调用self.user_settings方法,返回一个字典,字典再取attr属性
                val = self.user_settings[attr]
            except KeyError:
                # Fall back to defaults
                val = self.defaults[attr]

            # Coerce import strings into classes
            if attr in self.import_strings:
                val = perform_import(val, attr)

            # Cache the result
            self._cached_attrs.add(attr)
            setattr(self, attr, val)
            return val
user_settings方法 ,通过反射去setting配置文件里找REST_FRAMEWORK属性,找不到,返回空字典
    @property
    def user_settings(self):
        if not hasattr(self, ‘_user_settings‘):
            self._user_settings = getattr(settings, ‘REST_FRAMEWORK‘, {})
        return self._user_settings

源码注释2

响应器

解析成字符串 还是一个浏览器页面

from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer  #解析成字符串 还是浏览器样式的
# 不用动,就用全局配置即可默认配置中两个都有

全局使用

  在settings中配置 settings默认配置中两个都有

REST_FRAMEWORK = {
    ‘DEFAULT_PARSER_CLASSES‘:[
        ‘rest_framework.parsers.JSONParser‘,
    ],
    # 响应器 默认配置两个都由 这个是全局使用
# ‘DEFAULT_PARSER_CLASSES‘:[ ‘rest_framework.renderers.JSONRenderer‘,
#         ‘rest_framework.renderers.BrowsableAPIRenderer‘,]

}

局部使用

  在试图类中配置

renderer_classes = [JSONRenderer, BrowsableAPIRenderer]    
版本控制

作用用于控制版本    视图中 版本问题需要接受版本传过来的参数 注意是单个没有复数

内置版本控制

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/

局部使用

#在CBV类中加入
versioning_class = URLPathVersioning
 

全局使用

  在settings中配置

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

}

路由需要修改

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

在试图类中就可以通过,request.vesrsion取出当前访问哪个版本,相应的去执行相应版本的代码

示例

基于正则的方式

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r‘^(?P<version>[v1|v2]+)/test/‘, TestView.as_view(), name=‘test‘),
]

url

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.versioning import URLPathVersioning

class TestView(APIView):
    versioning_class = URLPathVersioning

    def get(self, request, *args, **kwargs):
        # 获取版本
        print(request.version)
        # 获取版本管理的类
        print(request.versioning_scheme)

        # 反向生成URL
        reverse_url = request.versioning_scheme.reverse(‘test‘, request=request)
        print(reverse_url)

        return Response(‘GET请求,响应内容‘)

views.py

View.py

        # 基于django内置,反向生成url
        from django.urls import reverse
        url2=reverse(viewname=‘ttt‘,kwargs={‘version‘:‘v2‘})
        print(url2)

源码分析

#执行determine_version,返回两个值,放到request对象里
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme

def determine_version(self, request, *args, **kwargs):
        #当配置上版本类之后,就会实例化
        if self.versioning_class is None:
            return (None, None)
        scheme = self.versioning_class()
        return (scheme.determine_version(request, *args, **kwargs), scheme)
分页

 常规分页   查看第n页 每页显示多少条

#分页                                 #常规分页                   偏移分页        cursor游标分页
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination

class PublishView(APIView):
    versioning_class = URLPathVersioning
    parser_classes = [JSONRenderer,]    #解析器

    def get(self,request,*args,**kwargs):
        #第一种方法,普通分页
        ‘‘‘
        查询出所有数据
        实例化产生一个普通分页对象
        每页显示多少条
        查询指定查询那一页的key值
        ‘‘‘
        ret= models.Publish.objects.all()
        page = PageNumberPagination()
        page.page_size = 3 #每页显示多少条
        page.page_query_param = ‘page‘  #按照page名词显示那一页

        # 前端控制每页显示多少条的查看key值必然要size=9,表示一页显示9条
        page.page_size_query_param = ‘size‘
        #控制每页最大显示多少,size如果传100,最多也是显示10
        page.max_page_size = 10
        ret_page = page.paginate_queryset(ret,request,self)
        #序列化
        pub_ser = PublishSerlizers(ret_page,many=True)
        #去settings中配置每页显示多少条    这个是全局配置的话 局部配置全局可以不配置

        return Response(pub_ser.data)

settings中配置

REST_FRAMEWORK = {
    # 每页显示两条
    ‘PAGE_SIZE‘:2
}

路由

  url(r‘^(?P<version>[v1|v2]+)/publish/‘,views.PublishView.as_view())

serializer

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

偏移分页   在第n个位置向前向后查询第n个位置

#分页                                 #常规分页                   偏移分页        cursor游标分页
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination

class PublishView(APIView):
    versioning_class = URLPathVersioning
    parser_classes = [JSONRenderer,]    #解析器

    def get(self,request,*args,**kwargs):   #偏移分页
        ret = models.Publish.objects.all()
        #实例化产生一个偏移分页对象
        page= LimitOffsetPagination()
        # 四个参数:
        # 从标杆位置往后取几个,默认取3个,可以指定
        page.default_limit = 3
        # 每条取得条数
        page.limit_query_param =‘limit‘
        # 标杆值,现象偏移到那个位置,如果offset=6, 表示当前在第6条位置上,往后取
        page.offset_query_param = ‘offset‘
        # 最大取10条
        page.max_limit = 10

        ret_page = page.paginate_queryset(ret,request,self)
        #序列化
        pub_ser= PublishSerlizers(ret_page,many=True)
        #取settings中配置每页显示多少条
        return page.get_paginated_response(pub_ser.data)

 cursor游标分页

from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination
class PublishView(APIView):
    versioning_class = URLPathVersioning
    parser_classes=[JSONParser,]

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

        ret_page = page.paginate_queryset(ret, request, self)
        # 序列化
        pub_ser = serializer.PublishSerializers(ret_page, many=True)
        # 去setting中配置每页显示多少条
        return page.get_paginated_response(pub_ser.data)

原文地址:https://www.cnblogs.com/lakei/p/11143411.html

时间: 2024-09-30 14:47:38

DRF url控制 解析器 响应器 版本控制 分页(常规分页,偏移分页,cursor游标分页)的相关文章

Django框架深入了解_04(DRF之url控制、解析器、响应器、版本控制、分页)

一.url控制 基本路由写法:最常用 from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^books/', views.Books.as_view()), url(r'^book/', views.Book.as_view()), url(r'^login/

DRF - 解析器组件

DRF之解析器组件 引入 Django RestFramework帮助我们实现了处理application/json协议请求的数据,另外,我们也提到,如果不使用DRF,直接从request.body里面拿到原始的客户端请求的字节数据,经过decode,然后json反序列化之后,也可以得到一个Python字典类型的数据. 但是,这种方式并不被推荐,因为已经有了非常优秀的第三方工具,那就是Django RestFramework的解析器组件. 解析器组件的使用 首先,来看看解析器组件的使用,稍后我们

【DRF解析器和渲染器】 &#423984;

目录 解析器 Django中的解析器 DRF中的解析器 DRF中的渲染器 原文: http://blog.gqylpy.com/gqy/294 "@ *** 解析器 解析器的作用就是服务端接收客户端传过来的数据,把数据解析成自己想要的数据类型的过程. 本质就是对请求体中的数据进行解析. Content-type:用于声明我给你传的是什么类型的数据 : application/x-ww-form-urlencoded 表单数据类型 : multipart/form-data 文件 : applic

详解Spring MVC 4之ViewResolver视图解析器

所有的We MVC框架都有一套它自己的解析视图的机制,Spring MVC也不例外,它使用ViewResolver进行视图解析,让用户在浏览器中渲染模型.ViewResolver是一种开箱即用的技术,能够解析JSP.Velocity模板和XSLT等多种视图. Spring处理视图最重要的两个接口是ViewResolver和View.ViewResolver接口在视图名称和真正的视图之间提供映射: 而View接口则处理请求将真正的视图呈现给用户.  1.几种常见的ViewResolver视图解析器

【原创】打造属于前端的Uri解析器

今天和大家一起讨论一下如何打造一个属于前端的url参数解析器.如果你是一个Web开发工程师,如果你了解过后端开发语言,譬如:PHP,Java等,那么你对下面的代码应该不会陌生: $kw = $_GET['keyword']; // PHP String kw = request.getParameter("keyword"); // JSP 对于后端语言,通过上面的代码我们可以很方便的获取到一个url请求中的参数值.但是,当我们在一个Web前端工程中需要使用到url参数的时候,我们熟悉

打造属于前端的Uri解析器

今天和大家一起讨论一下如何打造一个属于前端的url参数解析器.如果你是一个Web开发工程师,如果你了解过后端开发语言,譬如:PHP,Java等,那么你对下面的代码应该不会陌生: 1 $kw = $_GET['keyword']; // PHP 2 String kw = request.getParameter("keyword"); // JSP 对于后端语言,通过上面的代码我们可以很方便的获取到一个url请求中的参数值.但是,当我们在一个Web前端工程中需要使用到url参数的时候,

Spring MVC 4之ViewResolver视图解析器

所有的We MVC框架都有一套它自己的解析视图的机制,Spring MVC也不例外,它使用ViewResolver进行视图解析,让用户在浏览器中渲染模型.ViewResolver是一种开箱即用的技术,能够解析JSP.Velocity模板和XSLT等多种视图. Spring处理视图最重要的两个接口是ViewResolver和View.ViewResolver接口在视图名称和真正的视图之间提供映射: 而View接口则处理请求将真正的视图呈现给用户. 1.几种常见的ViewResolver视图解析器

使用amaze ui的分页样式封装一个通用的JS分页控件

作为一名码农,天天百度.偶尔谷歌,所有代码全靠copy,用第三方插件,偶尔也想着造造轮子,毕竟自己的骨肉总归比较亲. 今天有点空闲时间,想起我们公司之前套的页面的分页插件上还有bug,而写那个分页插件的小伙子已经离职,就决定自己来写一个. 首先,肯定是用我们的妹子UI做样式效果,毕竟开发妹子少,做的东西能和妹子沾点边,就沾一点,毕竟妹子比较好看. 然后 开始吧 第一步 找到妹子UI的分页HTML代码,一共有2种,我喜欢第一种,比较有颜 这是妹子UI的分页代码 <ul data-am-widget

路由控制,版本控制,解析器,响应器

路由控制 基本路由写法 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^register/', views.register), url(r'^login/', views.Login.as_view()), url(r'^test/', views.Authtest.as_view()), ] 第二种写法 必须继承只要继承了ViewSetMixin: urlpatterns = [ url(r'^publish/$', view