視圖集
視圖集有四個封裝類,ViewSet基礎封裝、GenericViewSet進一步封裝查詢集和序列化器、ModelViewSet進一步封裝action、ReadOnlyModelViewSet提取只讀action。以下是展開介紹。
一、ViewSet
# 源碼
class ViewSet(ViewSetMixin, views.APIView):
pass
沒錯,源碼中ViewSet就是隻有繼承而沒有實現任何方法&定義任何屬性,我們對APIView已經不陌生了,我上一篇DRF類視圖中有,它主要實現請求,響應,驗證,異常,限流等。主要看ViewSetMixin類。
class ViewSetMixin(object):
"""
Overrides `.as_view()` so that it takes an `actions` keyword that performs
the binding of HTTP methods to actions on the Resource.
For example
view = MyViewSet.as_view({'get': 'list', 'post': 'create'})
重寫了as_view方法,它需要執行一個`actions`關鍵字
HTTP方法綁定到資源上的操作
"""
def as_view(cls, actions=None, **initkwargs)
# 有興趣可以具體看實現,這裏就不復制了
pass
由源碼可以看出,僅僅提供了as_view方法將請求方法綁定到了actions關鍵字上,並沒有給出actions的具體實現,所以我們在使用ViewSet的時候,需要自己定義出action方法(查詢集和序列化器需要手動實例化調用、異常拋出等),然後通過as_view綁定請求方法即可。
# 舉例1.1
# 繼承視圖集ViewSet
class BooksAPIViewSet(ViewSet):
# 定義action中的list實現查詢所有
def list(self, request):
# 手動實現查詢集
books = BookInfo.books.all()
# 手動使用序列化器
serializer = BookInfoModelSerializer(books, many=True)
# 返回響應,APIView中實現的Response響應對象
return Response(serializer.data)
# 定義action中的retrieve檢索條件
def retrieve(self, request, pk):
try:
book = BookInfo.books.get(id=pk)
except BookInfo.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
serializer = BookInfoSerializer(book)
return Response(serializer.data)
我們實現了視圖集,爲了使他生效,我們還需要指定他們的url。
# as_view中實現了get->list的綁定,是我們發送的get /books/請求能夠生效
url(r'^books/$', views.BooksAPIViewSet.as_view({'get': 'list'})),
# 綁定get->retrieve,使得get /books/id/生效
url(r'^books/(?P<pk>\d+)/$', views.BooksAPIViewSet.as_view({'get': 'retrieve'})),
綜上:繼承ViewSet,需要自定義action,action中需要自己實現查詢集和序列化器,url中as_view需要綁定方法和action的對應關係
二、GenericViewSet
# 源碼
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
pass
同樣GenericViewSet類中也沒有任何實現,全部繼承自ViewSetMixin和GenericAPIView。DRF類視圖中有GenericAPIView的介紹,它主要實現指定查詢集queryset/get_queryset/get_object和指定序列化器serializer_class/get_serializer_class等。ViewSetMixin類剛剛提過主要重寫實現了as_view()用於request方法和action的綁定。注意:GenericViewSet一般需要和5種擴展類執行。
# 舉例1.2
# 繼承視圖集GenericViewSet
class BooksAPIViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, GenericViewSet):
# 指定查詢集和序列化器
# 之所以不用定義get/post方法,是因爲重寫了as_view方法,將get映射爲了list方法
# 之所以不用第一action,是因爲繼承了ListModelMixin等擴展類
queryset = BookInfo.books.all()
serializer_class = BookInfoModelSerializer
三、ModelViewSet
# 源碼
class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
pass
同樣,我們的ModelViewSet中也沒有任何功能的具體實現,單純的繼承五個擴展類的功能和GenericViewSet的功能。很明顯,五個擴展類主要實現了Create(增)List/Retrieve(查)Update(改)Destroy(刪)。GenericViewSet主要實現了序列化器的指定,查詢集的指定,和as_view的重寫。
四、ReadOnlyModelViewSet
# 源碼
class ReadOnlyModelViewSet(mixins.RetrieveModelMixin,
mixins.ListModelMixin,
GenericViewSet):
pass
由此可以看出ReadOnlyModelViewSet僅僅是查詢集。