试问如果当数据量特别大的时候,你是怎么解决分页的?
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 ]
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 ]
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__)
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对象,有上一页下一页
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)
写视图函数可继承的几个类,我们以前经常用到的是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)
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)
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 ]
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
用了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函数
]
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')
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 ]
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
自定制
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
继承关系
第一类:自定义路由
# 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:
用户请求头:
1、. json
访问URL:
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 ]
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)
2、.表格
访问URL:
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)
3、 Form表单
访问URL:
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)
4、 自定义显示模板
访问URL:
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 ]
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')
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>
5、浏览器格式API+JSON
访问URL:
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')
注意:如果同时多个存在时,自动根据URL后缀来选择渲染器。