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的寫法:
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擴展類使用,用來快速地實現列表視圖與詳情視圖。