DRF基類APIView的子類GenericAPIView

DRF的基類是APIView類,GenericAPIView類是APIView類的子類。數據庫

GenericAPIView類有什麼存在的意義呢?restful

其實,post

他主要提供了兩個用處:lua

1.提供關於數據庫查詢的屬性與方法spa

2.提供關於序列化器使用的屬性與方法rest

=================================================================================================================code

詳解:對象

先看一段小代碼比較好理解,(繼承APIView與繼承GenericAPIView的兩種不一樣的寫法,查詢多條數據時)blog

繼承APIView的寫法:
繼承

class DepartmentListAPIView(APIView):
    def get(self,request):
        """查詢多條數據"""
        dep = Department.objects.all()
        # 建立序列化器對象
        serializer = DepartmentSerializer(instance=dep,many=True)
        # 序列化:對象->字典
        data_dict = serializer.data
        # DRF的Response對象能夠把字典轉換爲請求頭指定的格式返回
        return Response(data=data_dict)

 

繼承GenericAPIView的寫法:

class DepartmentListAPIView(GenericAPIView):
    # querset與serializer_class是固定名字的!必定要指定
    # queryset指定數據庫所有數據的查詢集
    queryset = Department.objects.all()
    # serializer_class指定序列化器
    serializer_class = DepartmentSerializer
    def get(self,request):
        """查詢多條數據"""
        dep = self.get_queryset()
        serializer = self.get_serializer(dep,many=True)
        data_dict = serializer.data
        return Response(data=data_dict)

 

1.提供關於數據庫查詢的屬性與方法:

上面例子中,get_queryset()的方法,能夠取得數據庫查詢結果的查詢集queryset的內容。(注意,必定要經過get_query取得數據庫查詢的結果後再傳給序列化器,不能直接傳self.queryset給序列化器,由於get_query的源碼還有「Ensure queryset is re-evaluated on each request.」這一個步驟。)

 

2.提供關於序列化器使用的屬性與方法

上面的列子中,get_serializer()的方法,實際上就是取類屬性serializer_class的值

 

  • 更多的繼承APIView與繼承GenericAPIView的寫法:

繼承APIView的寫法:

class DepartmentListAPIView(APIView):
    def get(self,request):
        """查詢多條數據"""
        dep = Department.objects.all()
        # 建立序列化器對象
        serializer = DepartmentSerializer(instance=dep,many=True)
        # 序列化:對象->字典
        data_dict = serializer.data
        # DRF的Response對象能夠把字典轉換爲請求頭指定的格式返回
        return Response(data=data_dict)

    def post(self,request):
        """新增一條數據"""
        # DRF的Request對象直接把接受到的值轉換爲字典
        data_dict = request.data
        # 建立序列化器對象
        serializer = DepartmentSerializer(instance=None,data=data_dict)
        # 校驗校驗不經過,拋異常(反序列化的功能)
        serializer.is_valid(raise_exception=True)
        # 反序列化,把字典的數據存進數據庫
        serializer.save()
        # restful風格,新增要返回新增數據的那一列內容。用了序列化,把對象轉換爲字典,同時Response處理。
        return Response(data=serializer.data)


class DepartmentDetailAPIView(APIView):
    def get(self,request,pk):
        """查詢一條數據"""
        # 查詢出該條數據的對象
        try:
            dep = Department.objects.get(id=pk)
        except Department.DoesNotExist:
            return HttpResponse(status=status.HTTP_404_NOT_FOUND)
        # 建立序列化器對象
        serializer = DepartmentSerializer(instance=dep)
        # 序列化,把對象轉換爲字典,同時Response根據請求頭返回相應的格式
        return Response(data=serializer.data)

    def post(self,request,pk):
        """修改部門"""
        # DRF的Request對象直接把接受到的值轉換爲字典
        data_dict = request.data
        # 查詢出要修改的數據
        try:
            dep = Department.objects.get(id=pk)
        except Department.DoesNotExist:
            return HttpResponse(status=404)
        # 建立序列化器對象
        serializer = DepartmentSerializer(instance=dep,data=data_dict)
        # 反序列化,校驗參數是否正確,若不正確,拋異常
        serializer.is_valid(raise_exception=True)
        # 反序列化,把字典的數據存進數據庫
        serializer.save()
        # 序列化,把對象轉換爲字典。同時DRF的Response對象根據請求頭返回相應的格式
        return Response(serializer.data)

    def delete(self,request,pk):
        """刪除一個部門"""
        try:
            dep = Department.objects.get(id=pk)
        except Department.DoesNotExist:
            return HttpResponse(status=404)
        dep.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

 

繼承GenericAPIView的寫法:

class DepartmentListAPIView(GenericAPIView):
    # querset與serializer_class是固定名字的!
    # queryset指定數據庫所有數據的查詢集
    queryset = Department.objects.all()
    # serializer_class指定序列化器
    serializer_class = DepartmentSerializer

    def get(self,request):
        """查詢多條數據"""
        dep = self.get_queryset()
        serializer = self.get_serializer(instance=dep,many=True)
        data_dict = serializer.data
        return Response(data=data_dict)

    def post(self,request):
        """新增一條數據"""
        data_dict = request.data
        serializer = self.get_serializer(instance=None,data=data_dict)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)


class DepartmentDetailAPIView(GenericAPIView):

    queryset = Department.objects.all()
    serializer_class = DepartmentSerializer

    def get(self,request,pk):
        """查詢一條數據"""
        dep = self.get_object()  # 有主鍵用get_object(),get_object()方法根據pk參數查找queryset中的數據對象
        serializer = self.get_serializer(instance=dep)
        return Response(data=serializer.data)

    def post(self,request,pk):
        """修改部門"""
        data_dict = request.data
        dep = self.get_object()
        serializer = self.get_serializer(instance=dep,data=data_dict)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

    def delete(self,request,pk):
        """刪除一個部門"""
        dep = self.get_object()
        dep.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

 

 

  • 總結:

從上面的代碼能夠看出,繼承APIView和繼承GenerciAPIView的代碼量基本差很少。那麼GenericAPIView這個類有什麼實質的用處呢?

其實,

他是隻是爲了提供幾種方法給它的擴展類而已,GenericAPIView一般結合一個或多個Mixin擴展類使用,用來快速地實現列表視圖與詳情視圖。

相關文章
相關標籤/搜索