python之路_rest-framework之分页、路由、视图、渲染
一、分页
当访问的数据量特别大的时候,我们需要对数据进行分页显示,可以通过如下三种方式进行,分别介绍如下:
1、根据页码分页
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'^pagertest/',views.PagerView.as_view()), ]
视图代码:
from django.shortcuts import render from rest_framework.views import APIView from .models import UserInfo from rest_framework.response import Response from rest_framework import serializers from rest_framework.pagination import PageNumberPagination class MyPagination(PageNumberPagination): page_size = 2 #默认每页显示数据条数 page_query_param = "page" #第几页参数,在url中设置 page_size_query_param = "page_size" #定制每页显示的数据条数的参数,在url中设置 class PagerSerialize(serializers.ModelSerializer): '''数据序列化类''' class Meta: model = UserInfo fields = "__all__" depth = 2 #用于显示关联字段的对应的表的详细内容 class PagerView(APIView): def get(self,request,*args,**kwargs): user_list=UserInfo.objects.all() #根据url参数,获取分页数据 obj=MyPagination() page_user_list=obj.paginate_queryset(user_list,request,self) #数据进行序列化 ser=PagerSerialize(instance=page_user_list,many=True) response=obj.get_paginated_response(ser.data) #返回带上下页连接的数据 return response # return Response(ser.data)
2、根据位置和个数分页(limit offset)
视图代码:
from rest_framework.views import APIView from .models import UserInfo from rest_framework.response import Response from rest_framework import serializers from rest_framework.pagination import LimitOffsetPagination class MyPagination(LimitOffsetPagination): # 默认每页显示的数据条数 default_limit = 2 # URL中传入的显示数据条数的参数 limit_query_param = 'limit' # URL中传入的数据位置的参数 offset_query_param = 'offset' # 最大每页显得条数,默认为None max_limit = None class PagerSerialize(serializers.ModelSerializer): '''数据序列化''' class Meta: model = UserInfo fields = "__all__" depth = 2 #用于显示关联字段的对应的表的详细内容 class PagerView(APIView): def get(self,request,*args,**kwargs): user_list=UserInfo.objects.all() #根据url参数,获取分页数据 obj=MyPagination() page_user_list=obj.paginate_queryset(user_list,request,self) #数据进行序列化 ser=PagerSerialize(instance=page_user_list,many=True) response=obj.get_paginated_response(ser.data) #返回带上下页连接的数据 return response # return Response(ser.data) #不含上下页链接
3、游标分页
视图代码:
from rest_framework.views import APIView from .models import UserInfo from rest_framework.response import Response from rest_framework import serializers from rest_framework.pagination import CursorPagination class MyPagination(CursorPagination): # URL传入的游标参数 cursor_query_param = 'cursor' # 默认每页显示的数据条数 page_size = 2 # URL传入的每页显示条数的参数 page_size_query_param = 'page_size' # 每页显示数据最大条数 max_page_size = 1000 # 根据ID从大到小排列 ordering = "id" class PagerSerialize(serializers.ModelSerializer): '''数据序列化''' class Meta: model = UserInfo fields = "__all__" depth = 2 #用于显示关联字段的对应的表的详细内容 class PagerView(APIView): def get(self,request,*args,**kwargs): user_list=UserInfo.objects.all().order_by('-id') #将数据按照id从大到小排序 #根据url参数,获取分页数据 obj=MyPagination() page_user_list=obj.paginate_queryset(user_list,request,self) #数据进行序列化 ser=PagerSerialize(instance=page_user_list,many=True) response=obj.get_paginated_response(ser.data) #返回带上下页连接的数据 return response # return Response(ser.data) #不含上下页链接
总结:前两个者分页的本质是通过页码参数和每页显示数据条数等参数,对数据库中的所有数据进行重头遍历,然后展示符合参数要求对应的数据。当数据量很大的时候,这种分页方式对数据库查询的效率影响是很大的。但第三种游标方式分页的本质是通过记住当前页面数据的最大、最小id,翻页时根据记录的最大或者最小id,查询下一页对应的数据,这样就不会出现每一次翻页都会重头遍历数据的情况,大大的提高了查询效率。缺点是无法直接跳转到某一页。
二、路由
路由系统主要包含如下三种方式,介绍如下。
1、自定义路由
自定义路由主要有如下2种方式,均指向同一个视图,但是不同的路由用的场景或者说得到的结果是不同的,如下:
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), # 如下:http://127.0.0.1:8002/route/ GET: 查询(列表);POST: 增加 url(r'^route/$',views.RouteView.as_view()), url(r'^route\.(?P<format>\w+)$',views.RouteView.as_view()), # 必须为format,实例:http://127.0.0.1:8000/route.json
#如下:http://127.0.0.1:8002/route/1/ PUT: 更新;DELETE:删除;GET: 查询(单条数据) url(r'^route/(?P<pk>\d+)/$',views.RouteView.as_view()), url(r'^route/(?P<pk>\d+)\.(?P<format>\w+)$',views.RouteView.as_view()), #实例:http://127.0.0.1:8000/route/1.json ]
视图代码:
from rest_framework.views import APIView from .models import UserInfo from rest_framework.response import Response from rest_framework import serializers class RouteSerialize(serializers.ModelSerializer): class Meta: model = UserInfo fields = "__all__" depth = 2 #用于显示关联字段的对应的表的详细内容 class RouteView(APIView): def get(self, request, *args, **kwargs): pk=kwargs.get("pk") if pk: obj=UserInfo.objects.filter(pk=pk).first() ser=RouteSerialize(instance=obj,many=False) else: user_list=UserInfo.objects.all() ser=RouteSerialize(instance=user_list,many=True) return Response(ser.data)
2、半自动路由
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'^route/$', views.RouteView.as_view({'get':'list','post':'create'})),
url(r'^route/(?P<pk>\d+)$', views.RouteView.as_view({'get':'retrieve','put':'update','delete':'destroy',})), ]
如上实例,需要在as_view中设置请求类型及对应的处理方法。
view代码:
from .models import UserInfo from rest_framework import serializers from rest_framework.viewsets import GenericViewSet,ModelViewSet class RouteSerializer(serializers.ModelSerializer): class Meta: model = UserInfo fields = "__all__" class RouteView(ModelViewSet): #继承ModelViewSet queryset = UserInfo.objects.all() serializer_class = RouteSerializer
与手动url中的视图不同的是,此处不再继承APIView,而是ModelViewSet,因为其深度继承的关系,内部已经帮我们处理好了相关数据结果,因此并不需要我们做相应的判断并根据判断结果查询数据和返回数据。但是这种情况是的自定制变差。
3、全自动路由
url代码:
from django.conf.urls import url,include from django.contrib import admin from app01 import views from rest_framework.routers import DefaultRouter route = DefaultRouter() route.register('xxxxx',views.RouteView) ''' 本质如下四种: url(r'^xxxxx/', views.RouteView.as_view({'get':'list','post':'create'})), url(r'^xxxxx\.(?P<format>\w+)', views.RouteView.as_view({'get':'list','post':'create'})), url(r'^xxxxx/(?P<pk>\d+)', views.RouteView.as_view({'get':'retrieve','delete':'destroy','put':'update'})), url(r'^xxxxx/(?P<pk>\d+)\.(?P<format>\w+)', views.RouteView.as_view({'get':'retrieve','delete':'destroy','put':'update'})), ''' urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^', include(route.urls)), ]
view视图代码如半自动路由的相同。总结:推荐使用手动路由,方便自定制操作。
三、视图
写视图函数可继承的几个类,如要有如下三种,我们以前经常用到的是APIView,可定制性强。现在我们来了解一下其他的类。
from rest_framework.views import APIView from rest_framework.viewsets import GenericViewSet from rest_framework.viewsets import ModelViewSet
四、渲染