Django-rest-framework(三)view and viewsets使用
DRF 中有多種view和viewsets,我整理了一下,如下圖所示,接下來,我們分別了解下view,viewsets。
APIView
所有的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方法, 所以路由的註冊方式也一樣。所以在這裏不做演示了。
GenericAPIView
通用view的基礎視圖,其他的基礎view都是繼承了這個view,我們可以來看看源碼裏面實現了那些個方法
# 為了簡化,我刪掉了註釋和具體的實現, 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 來使用定義好的一些方法。
drf-mixins
在這裏,我們插入mixins這一部分,因為後面要介紹的這些view,viewset,都是使用了這種方式實現,在DRF中,有5種mixin,我們還是看看源碼裏面,
# 還是刪除了多余的代碼,只看有哪些方法, # 一共有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
本部分講解以APIView結尾這這些個views,包括CreateAPIView
,ListAPIView
,RetrieveAPIView
, DestroyAPIView
,UpdateAPIView
, ListCreateAPIView
, RetrieveUpdateAPIView
, RetrieveDestroyAPIView
, RetrieveUpdateDestroyAPIView
。這些都是通過繼承GenericAPIView
和不同的mixin實現,所以我們只選擇其中的一個來作為講解,下面看看ListAPIView
中的內容
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就完了。
viewsets
下面,我們來研究研究viewsets了,它不同與django原生的view,因為有修改分發方式,所以處理上會有些許的不同,還是老規矩,上源碼。
使用
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來實現我們所需要的接口。
路由註冊
因為改了分發方式,所以,不能簡單的像之前的 path(‘view‘, View.as_view())
一樣了,我們需要像下面這樣引入route。
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‘),
]
Django-rest-framework(三)view and viewsets使用