zoukankan      html  css  js  c++  java
  • REST framework (组件使用之视图、序列化)

    目录

    一、分页

    二、视图

    三、路由

    四、渲染器


     一、分页

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

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

    1、基于limit offset 做分页

    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
     1 from rest_framework.views import APIView
     2 from rest_framework.response import Response
     3 from app01.serializes.myserializes import MySerializes
     4 from rest_framework.pagination import LimitOffsetPagination
     5 from app01 import models
     6 
     7 # =========== 可以自己进行自定制分页,基于limitoffset===================
     8 class P1(LimitOffsetPagination):
     9     max_limit = 3  # 最大限制默认是None
    10     default_limit =2  # 设置每一页显示多少条
    11     limit_query_param = 'limit'  # 往后取几条
    12     offset_query_param = 'offset'  # 当前所在的位置
    13 
    14 class IndexView2(APIView):
    15     #使用http://127.0.0.1:8080/app01/v1/index2/?offset=2&limit=4可进行判断
    16     def get(self,request,*args,**kwargs):
    17         user_list = models.UserInfo.objects.all()
    18         p1 = P1()#注册分页
    19         page_user_list = p1.paginate_queryset(queryset=user_list,request=request,view=self)
    20         print('打印的是分页的数据',page_user_list)
    21         ser = MySerializes(instance=page_user_list,many=True)  #可允许多个
    22         # return Response(ser.data) #不含上一页下一页
    23         return p1.get_paginated_response(ser.data)
    24 
    25 =======================也可以用下面这种形式===========
    26 class BaseResponse(object):
    27     def __init__(self,code=1000,data=None,error=None):
    28         self.code = code
    29         self.data = data
    30         self.error = error
    31 class IndexView(views.APIView):
    32     '''第二种类表示的方式'''
    33     def get(self,request,*args,**kwargs):
    34         ret = BaseResponse()
    35         try:
    36             user_list = models.UserInfo.objects.all()
    37             p1 = P1()
    38             page_user_list = p1.paginate_queryset(queryset=user_list,request=request,view=self)
    39             ser = IndexSerializer(instance=page_user_list,many=True)
    40             ret.data = ser.data
    41             ret.next = p1.get_next_link()
    42         except Exception as e:
    43             ret.code= 1001
    44             ret.error = 'xxxx错误'
    45         return Response(ret.__dict__)
    views.py

    2、基于页码的分页

    from rest_framework.pagination import PageNumberPagination
     1 # ======================基于页码实现的分页==============
     2 class P2(PageNumberPagination):
     3     #默认每页显示的数据条数
     4     page_size = 2
     5     #获取url参数中设置的每页显示数据条数
     6     page_size_query_param = 'size'
     7     #获取url中传入的页码key
     8     page_query_param = 'page'
     9     #最大支持的每页显示的数据条数
    10     max_page_size = 5
    11 
    12 class IndexView3(APIView):
    13     #使用http://127.0.0.1:8080/app01/v1/index3/?page=1&page_size=1可进行判断
    14     def get(self,request,*args,**kwargs):
    15         user_list = models.UserInfo.objects.all()
    16         #实例化分页对象,获取数据库中的分页数据
    17         p2 = P2()
    18         print(p2.page_size_query_description)
    19         page_user_list = p2.paginate_queryset(queryset=user_list,request=request,view=self)
    20         print('打印的是分页的数据',page_user_list)
    21 
    22         #序列化对象
    23         ser = MySerializes(instance=page_user_list,many=True)  #可允许多个
    24 
    25         #生成分页和数据
    26         # return Response(ser.data) #不含上一页下一页
    27         return p2.get_paginated_response(ser.data)
    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变了

    1 urlpatterns = [
    2     url(r'^index3/$', views.IndexView3.as_view({'get': 'list','post':'create'})),
    3     url(r'^index3/(?P<pk>d+)/$', views.IndexView3.as_view({'get': 'retrieve'})),
    4    
    5 ]
    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后缀来选择渲染器。

  • 相关阅读:
    Installing Python Modules
    《利用Python 进行数据分析》
    使用Python进行描述性统计
    各种数字证书区别
    数字证书及CA的扫盲介绍
    expect学习笔记及实例详解
    使用openssl命令制作ecc证书
    那些证书相关的玩意儿(SSL,X.509,PEM,DER,CRT,CER,KEY,CSR,P12等)
    Openssl与私有CA搭建
    Openssl编程--源码分析
  • 原文地址:https://www.cnblogs.com/zhangliang91/p/10926939.html
Copyright © 2011-2022 走看看