DRF 中有多種view和viewsets,我整理了一下,以下圖所示,接下來,咱們分別瞭解下view,viewsets。
python
全部的view,viewsets都是繼承APIView,而APIView是繼承的django的django.views.generic.View, 而後增長了一些通用的操做,和重載了as_view
,dispatch
,options
,http_method_not_allowed
方法來適應DRF相關的配置和後續的使用。
在直接使用APIView的時候,就和使用django View同樣,分發規則也是同樣,GET請求分發到了get方法,POST請求分發到post方法, 因此路由的註冊方式也同樣。因此在這裏不作演示了。django
通用view的基礎視圖,其餘的基礎view都是繼承了這個view,咱們能夠來看看源碼裏面實現了那些個方法api
# 爲了簡化,我刪掉了註釋和具體的實現, class GenericAPIView(views.APIView): queryset = None # 這些會在mixins中用到 serializer_class = None lookup_field = 'pk' lookup_url_kwarg = None pagination_class = api_settings.DEFAULT_PAGINATION_CLASS def get_queryset(self): def get_object(self): def get_serializer(self, *args, **kwargs): def get_serializer_class(self): def get_serializer_context(self): def filter_queryset(self, queryset): @property def paginator(self): def paginate_queryset(self, queryset): def get_paginated_response(self, data):
能夠看出,在這裏,咱們定義了queryset,serializer相關的操做。咱們也能夠繼承GenericAPIView 來使用定義好的一些方法。app
在這裏,咱們插入mixins這一部分,由於後面要介紹的這些view,viewset,都是使用了這種方式實現,在DRF中,有5種mixin,咱們仍是看看源碼裏面,iview
# 仍是刪除了多餘的代碼,只看有哪些方法, # 一共有5種mixin,分別實現列表顯示,單個資源顯示,增長,修改,刪除操做。 # 後面講解的views,veiwsets就是經過繼承不一樣的mixin來實現對應功能 # 在這些方法的實現中,須要用到queryset,serializers,因此使用了mixin的時候,須要在view裏指定這兩個參數 class CreateModelMixin(object): def create(self, request, *args, **kwargs): class ListModelMixin(object): def list(self, request, *args, **kwargs): class RetrieveModelMixin(object): def retrieve(self, request, *args, **kwargs): class UpdateModelMixin(object): def update(self, request, *args, **kwargs): class DestroyModelMixin(object): def destroy(self, request, *args, **kwargs):
本部分講解以APIView結尾這這些個views,包括CreateAPIView
,ListAPIView
,RetrieveAPIView
, DestroyAPIView
,UpdateAPIView
, ListCreateAPIView
, RetrieveUpdateAPIView
, RetrieveDestroyAPIView
, RetrieveUpdateDestroyAPIView
。這些都是經過繼承GenericAPIView
和不一樣的mixin實現,因此咱們只選擇其中的一個來做爲講解,下面看看ListAPIView
中的內容post
class ListAPIView(mixins.ListModelMixin, GenericAPIView): def get(self, request, *args, **kwargs): return self.list(request, *args, **kwargs)
由於繼承的GenericAPIView,並無修改分發方式,因此也是GET請求分發到get方法,又由於繼承了ListModelMixin,因此會有list(self)方法,因而天然而然的,就在get方法中,調用self.list()去使用ListModelMixin中定義的方法。其餘的views相似,都是把對應的請求轉發到合適的mixin裏面。至此,drf中的views就完了。url
下面,咱們來研究研究viewsets了,它不一樣與django原生的view,由於有修改分發方式,因此處理上會有些許的不一樣,仍是老規矩,上源碼。spa
class ViewSetMixin(object): #代碼就不貼了,須要配合着看route才能理解,準備後面單獨開一篇來配合着route的處理來寫, #在這裏,咱們只須要知道在這個類中,重寫了分發規則as_view(), #規則大概來講就是,將對應的請求分發到list,create等在mixins定義了的方法中, 好比說,get請求分發到list,或者retrieve。 class GenericViewSet(ViewSetMixin, generics.GenericAPIView): pass class ReadOnlyModelViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, GenericViewSet): # model的只讀接口,實現了列表頁和詳情頁的 pass class ModelViewSet(mixins.CreateModelMixin, mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, mixins.ListModelMixin, GenericViewSet): # model 的增刪改查的接口 pass
經過源碼,咱們能夠發現,咱們能夠本身選擇繼承GenericViewSet 和對應的mixins來實現咱們所須要的接口。rest
由於改了分發方式,因此,不能簡單的像以前的 path('view', View.as_view())
同樣了,咱們須要像下面這樣引入route。code
from myapp.views import ViewSet from rest_framework.routers import DefaultRouter router = DefaultRouter() router.register(r'users', ViewSet) # url 爲 "/api/user/" urlpatterns = [ path('api/', include(router.urls), name='api'), ]