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'), ]