Django Rest Framework(分頁、視圖、路由、渲染器)

 1、分頁

試問若是當數據量特別大的時候,你是怎麼解決分頁的?html

  • 方式a、記錄當前訪問頁數的數據id
  • 方式b、最多顯示120頁等
  • 方式c、只顯示上一頁,下一頁,不讓選擇頁碼,對頁碼進行加密

一、基於limit offset 作分頁(如:在url後面加上?offset=0&limit=2,即表明從第0條開始,日後取2條(即1,2))python

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

 

二、基於頁碼的分頁web

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

 

三、基於Cursor的分頁數據庫

     2可能存在性能問題,若是用戶吧page給改的很大,查詢速度就會很慢。還有一種頁碼加密的方式,django

 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

2、視圖

寫視圖函數可繼承的幾個類,咱們之前常常用到的是APIView,如今咱們來了解一下其餘的類,其中一、三、4用到的最多json

須要導入的類api

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

一、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

二、GenericAPIView(APIView)app

 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

三、 GenericViewSet(ViewSetMixin, generics.GenericAPIView)ide

增 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

四、 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自定製

繼承關係

 

3、路由

第一類:自定義路由

# 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__"

4、渲染器

根據 用戶請求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

一、. 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

二、.表格

訪問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

三、 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

四、 自定義顯示模板

訪問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

五、瀏覽器格式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後綴來選擇渲染器。

相關文章
相關標籤/搜索