目錄
一、分頁
試問如果當資料量特別大的時候,你是怎麼解決分頁的?
- 方式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 ]
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 ]
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__)
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)
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變了
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 ]
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:
- 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 ]
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:
- 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)
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)
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 ]
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:
- 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')
注意:如果同時多個存在時,自動根據URL字尾來選擇渲染器。