zoukankan      html  css  js  c++  java
  • Django Rest Framework(分页、视图、路由、渲染器)

     一、分页

    试问如果当数据量特别大的时候,你是怎么解决分页的?

    • 方式a、记录当前访问页数的数据id
    • 方式b、最多显示120页等
    • 方式c、只显示上一页,下一页,不让选择页码,对页码进行加密

    1、基于limit offset 做分页(如:在url后面加上?offset=0&limit=2,即代表从第0条开始,往后取2条(即1,2))

    from rest_framework.pagination import LimitOffsetPagination
    1 urlpatterns = [
    2     url(r'^admin/', admin.site.urls),
    3     url(r'^app01/(?P<version>[v1|v2]+)/', include('app01.urls'))
    4 
    5 ]
    urls.py
    1 urlpatterns = [
    2     url(r'^index1/', views.IndexView1.as_view()),
    3     url(r'^index2/', views.IndexView2.as_view()),
    4     url(r'^index3/', views.IndexView3.as_view()),
    5     url(r'^index4/', views.IndexView4.as_view()),
    6     url(r'^index5/', views.IndexView5.as_view()),
    7 
    8 ]
    app01.url
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from app01.serializes.myserializes import MySerializes
    from rest_framework.pagination import LimitOffsetPagination
    from app01 import models
    
    # =========== 可以自己进行自定制分页,基于limitoffset===================
    class P1(LimitOffsetPagination):
        max_limit = 3  # 最大显示3条数据,当取的条数超过3条时,只显示前3条,不会再显示后面的,这个值默认是None,即不做限制
        default_limit =2  # 设置每一页显示多少条
        limit_query_param = 'limit'  # 往后取几条
        offset_query_param = 'offset'  # 当前所在的位置
    
    class IndexView2(APIView):
        #使用http://127.0.0.1:8080/app01/v1/index2/?offset=2&limit=4可进行判断
        def get(self,request,*args,**kwargs):
            user_list = models.UserInfo.objects.all()
            p1 = P1()#注册分页
            page_user_list = p1.paginate_queryset(queryset=user_list,request=request,view=self)
            print('打印的是分页的数据',page_user_list)
            ser = MySerializes(instance=page_user_list,many=True)  #可允许多个
            # return Response(ser.data) #不含上一页下一页
            return p1.get_paginated_response(ser.data)
    
    =======================也可以用下面这种形式===========
    class BaseResponse(object):
        def __init__(self,code=1000,data=None,error=None):
            self.code = code
            self.data = data
            self.error = error
    class IndexView(views.APIView):
        '''第二种类表示的方式'''
        def get(self,request,*args,**kwargs):
            ret = BaseResponse()
            try:
                user_list = models.UserInfo.objects.all()
                p1 = P1()
                page_user_list = p1.paginate_queryset(queryset=user_list,request=request,view=self)
                ser = IndexSerializer(instance=page_user_list,many=True)
                ret.data = ser.data
                ret.next = p1.get_next_link() #下一页链接
            except Exception as e:
                ret.code= 1001
                ret.error = 'xxxx错误'
            return Response(ret.__dict__)
    views.py

    2、基于页码的分页

    from rest_framework.pagination import PageNumberPagination
    # ======================基于页码实现的分页==============
    class P2(PageNumberPagination):
        #默认每页显示的数据条数
        page_size = 2
        #获取url参数中设置的每页显示数据条数
        page_size_query_param = 'size'
        #获取url中传入的页码key
        page_query_param = 'page'
        #最大支持的每页显示的数据条数
        max_page_size = 5
    
    class IndexView3(APIView):
        #使用http://127.0.0.1:8080/app01/v1/index3/?page=1&page_size=1可进行判断
        def get(self,request,*args,**kwargs):
            user_list = models.UserInfo.objects.all()
            #实例化分页对象,获取数据库中的分页数据
            p2 = P2()
            print(p2.page_size_query_description)
            page_user_list = p2.paginate_queryset(queryset=user_list,request=request,view=self)
            print('打印的是分页的数据',page_user_list)
    
            #序列化对象
            ser = MySerializes(instance=page_user_list,many=True)  #可允许多个
    
            #生成分页和数据
            # return Response(ser.data) #不含上一页下一页
            return p2.get_paginated_response(ser.data) # 是Response对象,有上一页下一页
    views.py

    3、基于Cursor的分页

         2可能存在性能问题,如果用户吧page给改的很大,查询速度就会很慢。还有一种页码加密的方式,

     1 # =====================基于Cursor的分页============
     2 class P3(CursorPagination):
     3     # URL传入的游标参数
     4     cursor_query_param = 'cursor'
     5     # 默认每页显示的数据条数
     6     page_size = 2
     7     # URL传入的每页显示条数的参数
     8     page_size_query_param = 'size'
     9     # 每页显示数据最大条数
    10     max_page_size = 3
    11 
    12     # 根据ID从大到小排列
    13     ordering = "id"
    14     
    15 class IndexView4(APIView):
    16     #使用http://127.0.0.1:8080/app01/v1/index4/?cursor=cj0xJnA9NA%3D%3D&size=3可进行判断
    17     def get(self,request,*args,**kwargs):
    18         user_list = models.UserInfo.objects.all().order_by('-id')
    19         p3 = P3()#注册分页
    20         page_user_list = p3.paginate_queryset(queryset=user_list,request=request,view=self)
    21         print('打印的是分页的数据',page_user_list)
    22         ser = MySerializes(instance=page_user_list,many=True)  #可允许多个
    23         # return Response(ser.data) #不含上一页下一页
    24         return p3.get_paginated_response(ser.data)
    views.py

    二、视图

    写视图函数可继承的几个类,我们以前经常用到的是APIView,现在我们来了解一下其他的类,其中1、3、4用到的最多

    需要导入的类

    from rest_framework.views import APIView
    from rest_framework.generics import GenericAPIView
    from rest_framework.viewsets import GenericViewSet
    from rest_framework.viewsets import ModelViewSet

    1、APIView

    1 class IndexView2(APIView):
    2     def get(self,request,*args,**kwargs):
    3         user_list = models.UserInfo.objects.all()
    4         ser = MySerializes(instance=user_list,many=True)
    5         return Response(ser.data)
    APIView

    2、GenericAPIView(APIView)

     1 from rest_framework.response import Response
     2 from rest_framework.generics import GenericAPIView
     3 from app01 import models
     4 from app01.serializes.myserializes import MySerializes
     5 from rest_framework.pagination import LimitOffsetPagination
     6 class P1(LimitOffsetPagination):
     7     max_limit = 3  # 最大限制默认是None
     8     default_limit =2  # 设置每一页显示多少条
     9     limit_query_param = 'limit'  # 往后取几条
    10     offset_query_param = 'offset'  # 当前所在的位置
    11 
    12 class IndexView1(GenericAPIView):
    13     queryset = models.UserInfo.objects.all()
    14     serializer_class = MySerializes
    15     pagination_class = P1
    16     def get(self,request,*args,**kwargs):
    17         user_list = self.get_queryset()
    18         p1 = P1()  #注册分页
    19         data = p1.paginate_queryset(queryset=user_list,request=request,view=self)  #获取分页的数据
    20         ser = self.get_serializer(instance=data,many=True) #序列化
    21         return Response(ser.data)
    GenericAPIView

    3、 GenericViewSet(ViewSetMixin, generics.GenericAPIView)

    增
        POST
        /users/
    删
        DELETE
        /users/1/#全部修改
        PUT
        /users/1/
        #局部修改
        patch
        /users/1/
    查
        GET
        /users/ 
        GET
        /users/1/
    在GET请求的时候如果带ID说明查一条,如果不带则查所有

    原始的

    1 urlpatterns = [
    2 
    3     url(r'^index/$', views.IndexView.as_view()),
    4     url(r'^index/(?P<pk>d+)$', views.IndexView.as_view()),
    5 ]
    urls.py
     1 class IndexView(views.APIView):
     2 
     3     def get(self,request,*args,**kwargs):
     4         pk = kwargs.get('pk')
     5         if pk:
     6             pass # 获取单条信息
     7         else:
     8             pass # 获取列表信息
     9 
    10     def post(self,request,*args,**kwargs):
    11         pass
    12 
    13     def put(self,request,*args,**kwargs):
    14         pass
    15 
    16     def patch(self,request,*args,**kwargs):
    17         pass
    18 
    19     def delete(self,request,*args,**kwargs):
    20                 pass
    views.py

    用了GenericViewSet这种方式的时候注意url变了

    urlpatterns = [
        url(r'^index3/$', views.IndexView3.as_view({'get': 'list','post':'create'})), #get方式执行list函数,post方式执行create函数
        url(r'^index3/(?P<pk>d+)/$', views.IndexView3.as_view({'get': 'retrieve'})),    #get方式执行retrieve函数
      
    ]
    urls.py
     1 class IndexView3(GenericViewSet):
     2     queryset = models.UserInfo.objects.all()
     3     serializer_class = MySerializes
     4     pagination_class = P1
     5 
     6     def list(self,request,*args,**kwargs):
     7         #获取列表信息
     8         return Response('...')
     9 
    10     def retrieve(self,request,*args,**kwargs):
    11         #获取单条数据
    12         return Response('xxx')
    GenericViewSet

    4、 ModelViewSet(mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,mixins.ListModelMixin,GenericViewSet)

    利用ModelViewSet增删改查不用自己写了,内部把增删改查都干了,当满足不了需求的时候我们也可以自定制

    1 urlpatterns = [
    2 
    3     url(r'^index4/', views.IndexView4.as_view({'get': 'list','post':'create'})),  #获取数据和添加数据
    4     url(r'^index4.(?P<format>[a-z0-9]+)/', views.IndexView4.as_view({'get': 'list','post':'create'})), #.json想让页面上显示成json格式
    5     url(r'^index4/(?P<pk>d+)/', views.IndexView4.as_view({'get': 'retrieve', 'delete': 'destroy','put':'partial_update'})), #查看单条,删除,修改数据
    6     url(r'^index4(?P<pk>d+).(?P<format>[a-z0-9]+)/', views.IndexView4.as_view({'get': 'retrieve', 'delete': 'destroy','put':'partial_update'})),
    7 
    8 ]
    urls.py
     1  注意啦:用ModelSerializer这种方法必须要用IndexSerializer(ModelSerializer)这种方式序列化
     2 class P2(PageNumberPagination):
     3     page_size = 3  #每一页显示的条数
     4     page_query_param = 'page' #获取参数中传入的页码
     5     page_size_query_param = 'size' #获取url参数中每页显示的数据条数
     6 
     7     max_page_size = 5
     8 
     9 class IndexSerializer(ModelSerializer):
    10     class Meta:
    11         model = models.UserInfo
    12         fields = "__all__"
    13 
    14 class IndexView4(ModelViewSet):
    15     queryset = models.UserInfo.objects.all()
    16     serializer_class = IndexSerializer
    17     pagination_class = P2
    views.py

    自定制

     1 class P2(PageNumberPagination):
     2     page_size = 3  #每一页显示的条数
     3     page_query_param = 'page' #获取参数中传入的页码
     4     page_size_query_param = 'size' #获取url参数中每页显示的数据条数
     5 
     6     max_page_size = 5
     7 
     8 class IndexSerializer(ModelSerializer):
     9     class Meta:
    10         model = models.UserInfo
    11         fields = "__all__"
    12 
    13 class IndexView4(ModelViewSet):
    14     queryset = models.UserInfo.objects.all()
    15     serializer_class = IndexSerializer
    16     pagination_class = P2
    17 
    18     def list(self, request, *args, **kwargs):
    19         '''获取get请求的所有'''
    20         pass
    21 
    22     def retrieve(self, request, *args, **kwargs):
    23         '''查看单条数据'''
    24         pass
    25     def destroy(self, request, *args, **kwargs):
    26         '''删除DELETE'''
    27         pass
    28     def create(self, request, *args, **kwargs):
    29         '''添加数据POST'''
    30         pass
    31     def update(self, request, *args, **kwargs):
    32         '''全部修改PUT'''
    33         pass
    34     def partial_update(self, request, *args, **kwargs):
    35         '''局部修改PATCH'''
    36         pass
    基于ModelViewSet自定制

    继承关系

    三、路由

    第一类:自定义路由

    # http://127.0.0.1:8000/api/v1/auth/
    url(r'^auth/$', views.AuthView.as_view()),
    # http://127.0.0.1:8000/api/v1/auth.json # 想要让页面显示json格式
    url(r'^auth.(?P<format>[a-z0-9]+)$', views.AuthView.as_view()),
    # http://127.0.0.1:8000/api/v1/auth/1/
    url(r'^auth/(?P<pk>d+)/$', views.AuthView.as_view()),
    # http://127.0.0.1:8000/api/v1/auth/1.json
    url(r'^auth/(?P<pk>d+).(?P<format>[a-z0-9]+)$', views.AuthView.as_view()),
    class AuthView(views.APIView):
    
        def get(self,request,*args,**kwargs):
            return Response('...')

    第二类:半自动路由

    url(r'^index/$', views.IndexView.as_view({'get':'list','post':'create'})),
    url(r'^index.(?P<format>[a-z0-9]+)$', views.IndexView.as_view({'get':'list','post':'create'})),
    url(r'^index/(?P<pk>d+)/$', views.IndexView.as_view({'get':'retrieve','delete':'destroy','put':'update','patch':'partial_update'})),
    url(r'^index(?P<pk>d+).(?P<format>[a-z0-9]+)$', views.IndexView.as_view({'get':'retrieve','delete':'destroy','put':'update','patch':'partial_update'})),
    
    class IndexView(viewsets.ModelViewSet):
        queryset = models.UserInfo.objects.all()
        serializer_class = IndexSerializer
        pagination_class = P2

    第三类:全自动路由,会自动生成四个url

    router = DefaultRouter()
    router.register('index',views.IndexViewSet)
    urlpatterns = [
        url(r'^', include(router.urls)),
    ]
    
    
    class IndexViewSet(viewsets.ModelViewSet):
        queryset = models.UserInfo.objects.all()
        serializer_class = IndexSerializer
        pagination_class = P2
        
        
        
    class IndexSerializer(serializers.ModelSerializer):
        class Meta:
            model = models.UserInfo
            fields = "__all__"

    四、渲染器

    根据 用户请求URL 或 用户可接受的类型,筛选出合适的 渲染组件。
    用户请求URL:

    • http://127.0.0.1:8000/test/?format=json
    • http://127.0.0.1:8000/test.json

    用户请求头:

    • Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

    1、. json

    访问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/ 
    1 from django.conf.urls import url, include
    2 from web.views import s11_render
    3 
    4 urlpatterns = [
    5     url(r'^test/$', s11_render.TestView.as_view()),
    6     url(r'^test.(?P<format>[a-z0-9]+)', s11_render.TestView.as_view()),
    7 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework import serializers
     6 
     7 from rest_framework.renderers import JSONRenderer
     8 
     9 from .. import models
    10 
    11 
    12 class TestSerializer(serializers.ModelSerializer):
    13     class Meta:
    14         model = models.UserInfo
    15         fields = "__all__"
    16 
    17 
    18 class TestView(APIView):
    19     renderer_classes = [JSONRenderer, ]
    20 
    21     def get(self, request, *args, **kwargs):
    22         user_list = models.UserInfo.objects.all()
    23         ser = TestSerializer(instance=user_list, many=True)
    24         return Response(ser.data)
    views.py

    2、.表格

    访问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/ 
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework import serializers
     6 
     7 from rest_framework.renderers import AdminRenderer
     8 
     9 from .. import models
    10 
    11 
    12 class TestSerializer(serializers.ModelSerializer):
    13     class Meta:
    14         model = models.UserInfo
    15         fields = "__all__"
    16 
    17 
    18 class TestView(APIView):
    19     renderer_classes = [AdminRenderer, ]
    20 
    21     def get(self, request, *args, **kwargs):
    22         user_list = models.UserInfo.objects.all()
    23         ser = TestSerializer(instance=user_list, many=True)
    24         return Response(ser.data)
    views.py

    3、 Form表单

    访问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/ 
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework import serializers
     6 
     7 from rest_framework.renderers import JSONRenderer
     8 from rest_framework.renderers import AdminRenderer
     9 from rest_framework.renderers import HTMLFormRenderer
    10 
    11 from .. import models
    12 
    13 
    14 class TestSerializer(serializers.ModelSerializer):
    15     class Meta:
    16         model = models.UserInfo
    17         fields = "__all__"
    18 
    19 
    20 class TestView(APIView):
    21     renderer_classes = [HTMLFormRenderer, ]
    22 
    23     def get(self, request, *args, **kwargs):
    24         user_list = models.UserInfo.objects.all().first()
    25         ser = TestSerializer(instance=user_list, many=False)
    26         return Response(ser.data)
    views.py

    4、 自定义显示模板

    访问URL:

    • http://127.0.0.1:8000/test/?format=html
    • http://127.0.0.1:8000/test.html
    • http://127.0.0.1:8000/test/ 
    1 from django.conf.urls import url, include
    2 from web.views import s11_render
    3 
    4 urlpatterns = [
    5     url(r'^test/$', s11_render.TestView.as_view()),
    6     url(r'^test.(?P<format>[a-z0-9]+)', s11_render.TestView.as_view()),
    7 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework import serializers
     6 from rest_framework.renderers import TemplateHTMLRenderer
     7 
     8 from .. import models
     9 
    10 
    11 class TestSerializer(serializers.ModelSerializer):
    12     class Meta:
    13         model = models.UserInfo
    14         fields = "__all__"
    15 
    16 
    17 class TestView(APIView):
    18     renderer_classes = [TemplateHTMLRenderer, ]
    19 
    20     def get(self, request, *args, **kwargs):
    21         user_list = models.UserInfo.objects.all().first()
    22         ser = TestSerializer(instance=user_list, many=False)
    23         return Response(ser.data, template_name='user_detail.html')
    views.py
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6 </head>
     7 <body>
     8     {{ user }}
     9     {{ pwd }}
    10     {{ ut }}
    11 </body>
    12 </html>
    userdetail.html

    5、浏览器格式API+JSON

    访问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/ 
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework import serializers
     6 
     7 from rest_framework.renderers import JSONRenderer
     8 from rest_framework.renderers import BrowsableAPIRenderer
     9 
    10 from .. import models
    11 
    12 
    13 class TestSerializer(serializers.ModelSerializer):
    14     class Meta:
    15         model = models.UserInfo
    16         fields = "__all__"
    17 
    18 
    19 class CustomBrowsableAPIRenderer(BrowsableAPIRenderer):
    20     def get_default_renderer(self, view):
    21         return JSONRenderer()
    22 
    23 
    24 class TestView(APIView):
    25     renderer_classes = [CustomBrowsableAPIRenderer, ]
    26 
    27     def get(self, request, *args, **kwargs):
    28         user_list = models.UserInfo.objects.all().first()
    29         ser = TestSerializer(instance=user_list, many=False)
    30         return Response(ser.data, template_name='user_detail.html')
    views.py

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

  • 相关阅读:
    牛客网 二叉树的镜像 JAVA
    牛客网 反转链表 JAVA
    牛客网 调整数组顺序使奇数位于偶数前面 JAVA
    Integer to Roman LeetCode Java
    Valid Number leetcode java
    Longest Common Prefix
    Wildcard Matching leetcode java
    Regular Expression Matching
    Longest Palindromic Substring
    Add Binary LeetCode Java
  • 原文地址:https://www.cnblogs.com/huchong/p/8450358.html
Copyright © 2011-2022 走看看