1. 程式人生 > >Django通用檢視APIView和檢視集ViewSet的介紹和使用

Django通用檢視APIView和檢視集ViewSet的介紹和使用

1.APIView

DRF框架的檢視的基類是 APIView
APIView的基本使用和View類似

  1. Django預設的View請求物件是 HttpRequest,REST framework 的請求物件是 Request。
    Request物件的資料是自動根據前端傳送資料的格式進行解析之後的結果。
    HttpRequest.GET ————> Request.query_params
    HttpRequest.POST 、HttpRequest.body————> Request.data

  2. Django預設的View響應物件是 HttpResponse(以及子類),REST framework 的響應物件是Response。
    構造方式:
    Response(data, status=None, template_name=None, headers=None, content_type=None)


    引數說明:

    • List item

    • data: 為響應準備的序列化處理後的資料;

    • status: 狀態碼,預設200;

    • template_name: 模板名稱,如果使用HTMLRenderer時需指明;

    • headers: 用於存放響應頭資訊的字典;

    • content_type: 響應資料的Content-Type,通常此引數無需傳遞,REST framework會根據前端所需型別資料來設定該引數。

  3. 支援定義的屬性:
    authentication_classes列表或元祖,身份認證類
    permissoin_classes列表或元祖,許可權檢查類
    throttle_classes列表或元祖,流量控制類。

  4. 在APIView中仍以常規的類檢視定義方法來實現get() 、post() 或者其他請求方式的方法。如下:


    ''' serializers.py '''

    class BookSerializer(serializers.ModelSerializer):
        
        class Meta:
            model = BookInfo    # 設定關聯模型     model就是關聯模型
            fields = '__all__'  # fields設定欄位   __all__表示所有欄位
            
    '''urls.py'''
url(r'^center/$',views.CenterView.as_view()) ''' views.py ''' class CenterView(APIView): def get(self,request): # 以前的 HttpRequest.GET # 現在的 # /center/?a=100&b=python params = request.query_params print(params) # 響應不同的第一個 dict = { 'name':'hello' } # return JsonResponse(dict) return Response(dict) # return HttpResponse('get') def post(self,request): # 以前的 HttpRequest.POST,HttpRequest.body # 現在 # form 表單提交資料 data = request.data print(data) return HttpResponse('post')

2.例項:使用APIView實現列表功能


    '''urls.py'''
    url(r'^books/$',views.BookListAPIView.as_view())

    '''views.py'''

    class BookListAPIView(APIView):
        '''書籍列表頁'''
        def get(self,request):
            # 1.獲取所有書籍
            books = BookInfo.objects.all()
            # 2.通過序列化器的轉換(模型轉換為JSON)
            serializer = BookSerializer(book,many=True)
            # 3.返回響應
            return Response(serializer.data)

        def post(self,request):

            # 1.接收引數
            data = request.data
            # 2.驗證引數(序列化器的校驗)
            serializer = BookSerializer(data=data)
            serializer.is_valid(raise_exception=True)
            # 3.資料入庫
            serializer.save()
            # 4.返回響應
            return Response(serializer.data)


3.GenericAPIView

  1. GenericAPIView是繼承自APIView,GenericAPIView肯定在APIView的基礎上 封裝了一些屬性和方法:增加了對於列表檢視和詳情檢視可能用到的通用方法和屬性的支援

    屬性:
    queryset 設定結果集
    serializer_class 設定序列化器
    lookup_field 查詢指定的物件

    方法:
    get_queryset(self) 返回檢視使用的查詢集
    get_serializer(self,_args, *_kwargs) 返回序列化器物件
    get_object(self) 返回詳情檢視所需的模型類資料物件

  2. 通常使用時,可搭配一個或多個擴充套件類(Mixin類,詳見4.)


    ##########GenericAPIView列表檢視##################

    '''urls.py'''
    url(r'^books/$',views.BookListGenericAPIView.as_view())



    '''views.py'''

    class BookListGenericAPIView(GenericAPIView):
        
        '''列表檢視'''

        # 查詢結果集
        queryset = BookInfo.objects.all()
        # 序列化器類
        serializer_class = BookSerializer

        def get(self,request):

            # 1.獲取所有書籍
            # books = BookInfo.objects.all()
            # 上面寫法也可以,但屬性就白白浪費了,沒有充分發揮屬性的作用

            books = self.get_queryset()

            # 2.建立序列化器
            # serializer = BookSerializer(books,many=True)
            # 以上寫法也可可以,但是還是沒有發揮屬性的作用

            # get_serializer()相當於BookSerializer()
            serializer = self.get_serializer(book,many=True)

            # 3.返回響應
            return Response(serializer.data)

            
        def post(self,request):

            # 1.獲取引數
            data = request.data
            # 2.建立序列化器
            serializer = self.get_serializer(data=data)
            # 3.校驗
            serializer.is_valid(raise_exception=True)
            # 4.儲存
            serializer.save()
            # 5.返回響應
            return Response(serializer.data)

	class BookDetailGenericAPIView(GenericAPIView):

        '''詳情檢視'''

        # 查詢結果集
        queryset = BookInfo.objects.all()
        # 序列化器類
        serializer_class = BookSerializer

        # 預設是pk   修改後以下引數都要變
        lookup_field = 'id'

        def get(self,request,id):

            # 1.獲取物件
            book = self.get_object()
            # 2.建立序列化器
            serializer = self.get_serializer(book)
            # 3.返回響應
            return Response(serializer.data)


        def put(self,request,id):

            # 1.獲取物件
            book = self.get_object()
            # 2.接收引數
            data = request.data
            # 3.建立序列化器
            serializer = self.get_serializer(instance=book,data=data)
            # 4.驗證
            serializer.is_valid(raise_exception=True)
            # 5.儲存(更新)
            serializer.save()
            # 3.返回響應
            return Response(serializer.data)



        def delete(self,request,pk):
            # 1.獲取物件
            book = self.get_object()
            # 2.刪除
            book.delete()
            # 3.返回響應
            return Response(status=status.HTTP_204_NO_CONTENT)


4.GenericAPIView和Mixin配合使用

mixin類提供用於提供基本檢視行為的操作。請注意,mixin類提供了操作方法,而不是直接定義處理程式方法,例如.get()和.post()。這允許更靈活的行為組合。

  • ListModelMixin
    提供一種.list(request, *args, **kwargs)實現列出查詢集的方法。
  • CreateModelMixin
    提供.create(request, *args, **kwargs)實現建立和儲存新模型例項的方法。
  • RetrieveModelMixin
    提供一種.retrieve(request, *args, **kwargs)方法
  • UpdateModelMixin
    提供.update(request, *args, **kwargs)實現更新和儲存現有模型例項的方法。
  • DestroyModelMixin
    提供一種.destroy(request, *args, **kwargs)實現刪除現有模型例項的方法。

    '''urls.py'''
 	url(r'^booklist/$',views.BookListGenericMixinAPIView.as_view())


    '''views.py'''

    # ListModelMixin        獲取全部物件(列表)
    # CreateModelMixin      新增資源
    # RetrieveModelMixin    獲取一個資源
    # UpdateModelMixin      更新一個資源
    # DestoryModelMixin     刪除一個資源

    class BookListGenericMixinAPIView(ListModelMixin,CreateModelMixin,GenericAPIView):

       # 查詢結果集
        queryset = BookInfo.objects.all()
        # 序列化器類
        serializer_class = BookSerializer

        def get(self,request):

            return self.list(request)

        def post(self,request):

            return self.create(request)

        def post(self,request):

            return self.create(request)
        
    class BookDetailGenericMixinAPIView(R,U,D):

        def get(self,request):

            return self.retrieve(request)

        def put(self,request):

            return self.update(request)

        def delete(self,request):

            return self.destroy(request)


6.三級檢視

  • CreateAPIView
    提供post方法處理程式。

  • ListAPIView
    用於只讀端點以表示模型例項的集合。
    提供get方法處理程式。

  • RetrieveAPIView
    用於表示單個模型例項的只讀端點。
    提供get方法處理程式。

  • DestroyAPIView
    用於單個模型例項的僅刪除端點。
    提供delete方法處理程式。

  • UpdateAPIView
    用於單個模型例項的僅更新端點。
    提供put和patch方法處理程式。

  • ListCreateAPIView
    用於讀寫端點以表示模型例項的集合。
    提供get和post方法處理程式。

  • RetrieveUpdateAPIView
    用於讀取或更新端點以表示單個模型例項。
    提供get,put並且patch方法處理。

  • RetrieveDestroyAPIView
    用於讀取或刪除端點以表示單個模型例項。
    提供get和delete方法處理程式。

  • RetrieveUpdateDestroyAPIView
    用於讀寫 - 刪除端點以表示單個模型例項。
    提供get,put,patch和delete方法處理。


    '''urls.py'''
    url(r'^booklist/$',views.Book2ListAPIView.as_view())


    '''views.py'''

    class Book2ListAPIView(ListAPIView):

        # 查詢結果集
        queryset = BookInfo.objects.all()
        # 序列化器類
        serializer_class = BookSerializer

7.檢視集Viewset

  1. APIView,GenericAPIView,ListAPIView 都是繼承自View
    繼承自View的類檢視,只能定義相同的一個函式名,例如:只能定義一個get,post方法

  2. 列表檢視中 設定了 queryset,serializer_class get,post
    詳情檢視中也設定了 queryset,serializer_class get,put,delete
    能否將這兩個檢視合併???
    我們是可以將 列表和詳情檢視 組合到一起的,稱之為 檢視集 ViewSet
    它不提供任何方法處理程式( 如get(),post() ),而是提供了諸如list() create()之類的操作


    class BookViewSet(ViewSet):

        # get
        def list(self,request):
            queryset = BookInfo.objects.all()
            serializer = BookInfoSerializer(queryset,many=True)
            return Response(serializer.data)
        # get
        def retrieve(self,request,pk=None):
            queryset = BookInfo.objects.all()
            user = get_object_or_404(queryset, pk=pk)
            serializer = BookInfoSerializer(user)
            return Response(serializer.data)


    '''urls.py'''
    # 繼承自 ViewSet的url 可以自動生成
    from rest_framework.routers import DefaultRouter,SimpleRouter

    # Router:的相同點  都是可以自動生成url
    # Router:的不同點
        #       DefaultRouter    可以在根路由下顯示
        #       SimpleRouter     不可以在根路由下顯示,且會報404
    
   
    # 1.建立router物件
    router = DefaultRouter()

    # 2.設定正則
    # router的原理
    # router 會自動生成兩個url   一個是列表檢視的url  另一個是詳情檢視的url

    # 引數1:正則,  只需要設定列表檢視和詳情檢視公共的部分
        # 例如:  booklist/是列表檢視
                #   booklist/id 是詳情檢視
                # 公共部分是 booklist  不包括/
    # 引數2:檢視集
    # 引數3:base_name  只是我們名字url name的一個字首
            # 例如:列表檢視的名字: base_name-list     book-list
            #       詳情檢視的名字: base_name-detail    book-detail
    router.register(r'booklist',views.BookModelViewset,base_name='book')

    # 3.將自動生成的url  新增到 urlpatterns中
    # router.urls  urls 這個屬性 存放了自動生成的url
    urlpatterns +=  router.urls




    # ModelViewSet 其實就是繼承自 GenericAPIView,同時繼承了5個擴充套件
    class BookModelViewset(ModelViewSet):

        queryset = BookInfo.objects.all()
        serializer_class = BookSerializer