11## RESTful架构和DRF进阶
22
3- 除了上一节讲到的方法,使用DRF创建REST风格的数据接口还有CBV (基于类的视图)的方式。使用CBV创建数据接口的特点是代码简单,开发效率高,但是没有FBV(基于函数的视图)灵活,因为使用FBV的方式,数据接口对应的视图函数执行什么样的代码以及返回什么的数据是高度可定制的。下面我们以定制学科的数据接口为例,讲解通过CBV方式定制数据接口的具体做法。
3+ 除了上一节讲到的方法,使用DRF创建REST风格的数据接口也可以通过CBV (基于类的视图)的方式。使用CBV创建数据接口的特点是代码简单,开发效率高,但是没有FBV(基于函数的视图)灵活,因为使用FBV的方式,数据接口对应的视图函数执行什么样的代码以及返回什么的数据是高度可定制的。下面我们以定制学科的数据接口为例,讲解通过CBV方式定制数据接口的具体做法。
44
5- ### 使用ModelViewSet
5+ ### 使用CBV
66
7- 修改之前项目中的` polls/views.py ` ,去掉` show_subjects ` 视图函数,添加一个名为` SubjectViewSet ` 的类。
7+ #### 继承APIView的子类
8+
9+ 修改之前项目中的` polls/views.py ` ,去掉` show_subjects ` 视图函数,添加一个名为` SubjectView ` 的类,该类继承自` ListAPIView ` ,` ListAPIView ` 能接收GET请求,它封装了获取数据列表并返回JSON数据的` get ` 方法。` ListAPIView ` 是` APIView ` 的子类,` APIView ` 还有很多的子类,例如` CreateAPIView ` 可以支持POST请求,` UpdateAPIView ` 可以支持PUT和PATCH请求,` DestoryAPIView ` 可以支持DELETE请求。` SubjectView ` 的代码如下所示。
10+
11+ ``` Python
12+ class SubjectView (ListAPIView ):
13+ # 通过queryset指定如何获取学科数据
14+ queryset = Subject.objects.all()
15+ # 通过serializer_class指定如何序列化学科数据
16+ serializer_class = SubjectSerializer
17+ ```
18+
19+ 刚才说过,由于` SubjectView ` 的父类` ListAPIView ` 已经实现了` get ` 方法来处理获取学科列表的GET请求,所以我们只需要声明如何获取学科数据以及如何序列化学科数据,前者用` queryset ` 属性指定,后者用` serializer_class ` 属性指定。要使用上面的` SubjectView ` ,需要修改` urls.py ` 文件,如下所示。
20+
21+ ``` Python
22+ urlpatterns = [
23+ path(' api/subjects/' , SubjectView.as_view()),
24+ ]
25+ ```
26+
27+ 很显然,上面的做法较之之前讲到的FBV要简单很多。
28+
29+ #### 继承ModelViewSet
30+
31+ 如果学科对应的数据接口需要支持GET、POST、PUT、PATCH、DELETE请求来支持对学科资源的获取、新增、更新、删除操作,更为简单的做法是继承` ModelViewSet ` 来编写学科视图类。再次修改` polls/views.py ` 文件,去掉` SubjectView ` 类,添加一个名为` SubjectViewSet ` 的类,代码如下所示。
832
933``` Python
1034class SubjectViewSet (ModelViewSet ):
1135 queryset = Subject.objects.all()
1236 serializer_class = SubjectSerializer
1337```
1438
15- 通过查看` ModelViewSet ` 类的源代码可以发现,该类共有6个父类,其中前5个父类分别实现创建学科、 获取指定学科、更新指定学科、删除指定学科和获取学科列表的数据接口 ,对应的方法分别是` create ` 、` retrieve ` 、` update ` 、` destroy ` 和` list ` 。由于ModelViewSet的父类中已经实现了这些方法,所以我们几乎没有编写任何代码就完成了学科数据接口的开发,我们要做的仅仅是指出如何获取到学科数据 (通过` queryset ` 属性指定)以及如何序列化学科数据 (通过` serializer_class ` 属性指定)。
39+ 通过查看` ModelViewSet ` 类的源代码可以发现,该类共有6个父类,其中前5个父类分别实现对POST(新增学科)、GET( 获取指定学科)、PUT/PATCH(更新学科)、DELETE(删除学科)和GET(获取学科列表)操作的支持 ,对应的方法分别是` create ` 、` retrieve ` 、` update ` 、` destroy ` 和` list ` 。由于 ` ModelViewSet ` 的父类中已经实现了这些方法,所以我们几乎没有编写任何代码就完成了学科数据全套接口的开发,我们要做的仅仅是指出如何获取到数据 (通过` queryset ` 属性指定)以及如何序列化数据 (通过` serializer_class ` 属性指定),这一点跟上面继承 ` APIView ` 的子类做法是一致的 。
1640
1741``` Python
1842class ModelViewSet (mixins .CreateModelMixin ,
@@ -28,13 +52,17 @@ class ModelViewSet(mixins.CreateModelMixin,
2852 pass
2953```
3054
31- 要使用上面的` SubjectViewSet ` ,需要在` urls.py ` 文件中进行URL映射。不同于之前的视图函数映射URL的方式,我们需要先创建一个路由器对象并通过该对象注册 ` SubjectViewSet ` ,然后将注册成功后生成的URL一并添加到` urlspattern ` 列表中,代码如下所示。
55+ 要使用上面的` SubjectViewSet ` ,需要在` urls.py ` 文件中进行URL映射。由于 ` ModelViewSet ` 相当于是多个视图函数的汇总,所以不同于之前映射URL的方式,我们需要先创建一个路由器并通过它注册 ` SubjectViewSet ` ,然后将注册成功后生成的URL一并添加到` urlspattern ` 列表中,代码如下所示。
3256
3357``` Python
3458router = DefaultRouter()
3559router.register(' api/subjects' , SubjectViewSet)
3660urlpatterns += router.urls
3761```
3862
39- ### 使用APIView的子类
63+ 除了` ModelViewSet ` 类外,DRF还提供了一个名为` ReadOnlyModelViewSet ` 的类,从名字上就可以看出,该类是只读视图的集合,也就意味着,继承该类定制的数据接口只能支持GET请求,也就是获取单个资源和资源列表的请求。
64+
65+ ### 数据分页
66+
67+ ### 数据筛选
4068
0 commit comments