除了上一节讲到的方法,使用DRF创建REST风格的数据接口也可以通过CBV(基于类的视图)的方式。使用CBV创建数据接口的特点是代码简单,开发效率高,但是没有FBV(基于函数的视图)灵活,因为使用FBV的方式,数据接口对应的视图函数执行什么样的代码以及返回什么的数据是高度可定制的。下面我们以定制学科的数据接口为例,讲解通过CBV方式定制数据接口的具体做法。
修改之前项目中的polls/views.py
,去掉show_subjects
视图函数,添加一个名为SubjectView
的类,该类继承自ListAPIView
,ListAPIView
能接收GET请求,它封装了获取数据列表并返回JSON数据的get
方法。ListAPIView
是APIView
的子类,APIView
还有很多的子类,例如CreateAPIView
可以支持POST请求,UpdateAPIView
可以支持PUT和PATCH请求,DestoryAPIView
可以支持DELETE请求。SubjectView
的代码如下所示。
class SubjectView(ListAPIView):
# 通过queryset指定如何获取学科数据
queryset = Subject.objects.all()
# 通过serializer_class指定如何序列化学科数据
serializer_class = SubjectSerializer
刚才说过,由于SubjectView
的父类ListAPIView
已经实现了get
方法来处理获取学科列表的GET请求,所以我们只需要声明如何获取学科数据以及如何序列化学科数据,前者用queryset
属性指定,后者用serializer_class
属性指定。要使用上面的SubjectView
,需要修改urls.py
文件,如下所示。
urlpatterns = [
path('api/subjects/', SubjectView.as_view()),
]
很显然,上面的做法较之之前讲到的FBV要简单很多。
如果学科对应的数据接口需要支持GET、POST、PUT、PATCH、DELETE请求来支持对学科资源的获取、新增、更新、删除操作,更为简单的做法是继承ModelViewSet
来编写学科视图类。再次修改polls/views.py
文件,去掉SubjectView
类,添加一个名为SubjectViewSet
的类,代码如下所示。
class SubjectViewSet(ModelViewSet):
queryset = Subject.objects.all()
serializer_class = SubjectSerializer
通过查看ModelViewSet
类的源代码可以发现,该类共有6个父类,其中前5个父类分别实现对POST(新增学科)、GET(获取指定学科)、PUT/PATCH(更新学科)、DELETE(删除学科)和GET(获取学科列表)操作的支持,对应的方法分别是create
、retrieve
、update
、destroy
和list
。由于ModelViewSet
的父类中已经实现了这些方法,所以我们几乎没有编写任何代码就完成了学科数据全套接口的开发,我们要做的仅仅是指出如何获取到数据(通过queryset
属性指定)以及如何序列化数据(通过serializer_class
属性指定),这一点跟上面继承APIView
的子类做法是一致的。
class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
"""
A viewset that provides default `create()`, `retrieve()`, `update()`,
`partial_update()`, `destroy()` and `list()` actions.
"""
pass
要使用上面的SubjectViewSet
,需要在urls.py
文件中进行URL映射。由于ModelViewSet
相当于是多个视图函数的汇总,所以不同于之前映射URL的方式,我们需要先创建一个路由器并通过它注册SubjectViewSet
,然后将注册成功后生成的URL一并添加到urlspattern
列表中,代码如下所示。
router = DefaultRouter()
router.register('api/subjects', SubjectViewSet)
urlpatterns += router.urls
除了ModelViewSet
类外,DRF还提供了一个名为ReadOnlyModelViewSet
的类,从名字上就可以看出,该类是只读视图的集合,也就意味着,继承该类定制的数据接口只能支持GET请求,也就是获取单个资源和资源列表的请求。