drf 下的 url控制 解析器 响应器 版本控制 分页

一、url  控制

前戏准备:

models.py:


class Author(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    hobby = models.IntegerField(choices=((1,'basketball'),(2,'soccer'),(3,'baseball')),default=1)


class Book(models.Model):
    title = models.CharField(max_length=32)
    publish = models.CharField(max_length=32)
    create_time = models.DateTimeField(auto_now_add=True)
    author = models.ManyToManyField(to='Author')

自定义文件下:Myserializer.py

from app01 import models
from rest_framework.serializers import ModelSerializer,Serializer,SerializerMethodField
from rest_framework import serializers

class AuthorSerializer(ModelSerializer):
    class Meta:
        model = models.Author
        fields = '__all__'
        
    # 可以解决choice字段前端可以取道想要的表示数据,发到后端的时候,发对应的序号就行,好用
    hobby = serializers.SerializerMethodField()
    def get_hobby(self,obj):
        return obj.get_hobby_display()

class BookSerializer(ModelSerializer):
    class Meta:
        model = models.Book
        fields = '__all__'

视图层

from app01 import models
from app01.MyseriaLizer import AuthorSerializer ,BookSerializer
from rest_framework.viewsets import ModelViewSet

class Author(ModelViewSet):

    queryset = models.Author.objects.all()
    serializer_class = AuthorSerializer


class Book(ModelViewSet):
    queryset = models.Book.objects.all()
    serializer_class = BookSerializer

路由层:

from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
from rest_framework.routers import SimpleRouter,DefaultRouter


#使用 Simplerouter  自动生成两种路由

router = SimpleRouter()
router.register('book',views.Book)
router.register('author',views.Author)
#多个路由直接再注册一次就ok

 url(r'',include(router.urls))


其自动生成的路径为:

^book/$ [name='book-list']
^book/(?P<pk>[^/.]+)/$ [name='book-detail']
^author/$ [name='author-list']
^author/(?P<pk>[^/.]+)/$ [name='author-detail']


#使用 DefaultRouter  自动生成6种路由
router = DefaultRouter()  #用法一样,将类换一下即可
router.register('book',views.Book)

    url(r'',include(router.urls))

其自动生成的路径:
^book/$ [name='book-list']
^book.(?P<format>[a-z0-9]+)/?$ [name='book-list']
^book/(?P<pk>[^/.]+)/$ [name='book-detail']
^book/(?P<pk>[^/.]+).(?P<format>[a-z0-9]+)/?$ [name='book-detail']
^$ [name='api-root']
^.(?P<format>[a-z0-9]+)/?$ [name='api-root']
二、解析器

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

在视图层使用

from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer
class Author(ModelViewSet):
    renderer_classes = [JSONRenderer,]  #局部使用
    queryset = models.Author.objects.all()
    serializer_class = AuthorSerializer

全局使用:
先在settings里配置:
REST_FRAMEWORK = {
                    "DEFAULT_PARSER_CLASSES":[
                        'rest_framework.parsers.JSONParser',
                    ]
                }
局部使用:直接在视图类中使用:parser_classes=[JSONParser,]
三、版本控制

用来版本的控制

drf内置的版本控制类:
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

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


路由层:

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



视图层:
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请求,响应内容')



补充:
# 基于django内置,反向生成url
        from django.urls import reverse
        url2=reverse(viewname='ttt',kwargs={'version':'v2'})
        print(url2)
批量插入数据:
def get(self,request,*args,**kwargs):
      li = []
        for i in range(100):
            li.append(models.Test(classes='%s班级'%i,grade='第%s人'%i))
        models.Test.objects.bulk_create(li)
        return Response()
四、分页器

常规分页:
  基本使用:
from rest_framework.pagination import PageNumberPagination

class Test(APIView):
    def get(self,request,*args,**kwargs):
        #获得所有要分页的数据
        ret = models.Test.objects.all()
        # 实例化产生对象
        page = PageNumberPagination()
        #  控制每页显示的条数
        page.page_size = 5  # 这一步也可交给settings配置,不过需要记住优先顺序!
        # 指定查询哪一页的key值,在url后输入即可,记得带上?
        page.page_query_param = 'page'
        前端控制每页显示多少条的查询key值  可以改变改变默认值
         page.page_size_query_param = 'size'
        # 控制每页最多显示的条数
        page.max_page_size = 10
        #在数据库中获取分页的数据
        ret_page = page.paginate_queryset(ret,request,view=self)
        test_ser = TestSerializer(instance=ret_page,many=True)
       # return Response(test_ser.data)  正常使用
       #这个也是返回Response对象,但是比基本的多了上一页,下一页,和总数据条数
        return page.get_paginated_response(ser.data)



路由层: url(r
'^test/',views.Test.as_view()) 自定义序列化层: class TestSerializer(ModelSerializer): class Meta: model = models.Test fields = '__all__'      #exclude = (当前的不会出现,其他的会有的) 注:在使用过程中发现 :会报错,但不影响代码的执行 UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list 经过google查询资料,发现是获取所有queryset对象时没有排序! 因此只需要获取数据时: ret = models.Test.objects.all().order_by('pk')即可

对于上述default_limit配置无效的解决:
注意代码的顺序:即将
ret_page = page.paginate_queryset(ret, request, view=self)
test_ser = TestSerializer(instance=ret_page,many=True)
放置最后即可!


偏移分页: LimitOffsetPagination
from rest_framework.pagination import LimitOffsetPagination
class Test(APIView):
def get(self, request, *args, **kwargs):
ret = models.Test.objects.all().order_by('pk')
# 实例化产生对象
page = LimitOffsetPagination()
# 固定写法
ret_page = page.paginate_queryset(ret,request,view=self)
# page.default_limit = 2 不知为何,这种配置没用,只能手动指定 limit 的数字,显示多少条
page.limit_query_param = 'limit'
#标杆值,现在偏移到哪个位置
page.offset_query_param = 'offset'
# 最大往后去的条数
page.max_limit = 10
test_ser = TestSerializer(instance=ret_page,many=True)
return Response(test_ser.data)





加密分页 :只能看上一页,下一页,查询速度快 CursorPagination
from rest_framework.pagination import CursorPagination
class Test(APIView):
def get(self,request,*args,**kwargs):
page = CursorPagination()
ret = models.Test.objects.all()
# 每页显示的大小
page.page_size = 3
#查询的key值
page.cursor_query_param = 'cursor'
# 按什么来排序
page.ordering = 'id'
ret_page = page.paginate_queryset(ret,request,view=self)
page_ser = TestSerializer(instance=ret_page,many=True)
# 使用get_paginated_response 可以避免页码被猜到
return page.get_paginated_response(page_ser.data)
原文地址:https://www.cnblogs.com/changwenjun-666/p/11140892.html