50.RESTful架构和DRF进阶.md 4.2 KB
Newer Older
J
jackfrued 已提交
1
## RESTful架构和DRF进阶
2

J
jackfrued 已提交
3
除了上一节讲到的方法,使用DRF创建REST风格的数据接口也可以通过CBV(基于类的视图)的方式。使用CBV创建数据接口的特点是代码简单,开发效率高,但是没有FBV(基于函数的视图)灵活,因为使用FBV的方式,数据接口对应的视图函数执行什么样的代码以及返回什么的数据是高度可定制的。下面我们以定制学科的数据接口为例,讲解通过CBV方式定制数据接口的具体做法。
J
jackfrued 已提交
4

J
jackfrued 已提交
5
### 使用CBV
J
jackfrued 已提交
6

J
jackfrued 已提交
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
#### 继承APIView的子类

修改之前项目中的`polls/views.py`,去掉`show_subjects`视图函数,添加一个名为`SubjectView`的类,该类继承自`ListAPIView``ListAPIView`能接收GET请求,它封装了获取数据列表并返回JSON数据的`get`方法。`ListAPIView``APIView` 的子类,`APIView`还有很多的子类,例如`CreateAPIView`可以支持POST请求,`UpdateAPIView`可以支持PUT和PATCH请求,`DestoryAPIView`可以支持DELETE请求。`SubjectView` 的代码如下所示。

```Python
class SubjectView(ListAPIView):
    # 通过queryset指定如何获取学科数据
    queryset = Subject.objects.all()
    # 通过serializer_class指定如何序列化学科数据
    serializer_class = SubjectSerializer
```

刚才说过,由于`SubjectView`的父类`ListAPIView`已经实现了`get`方法来处理获取学科列表的GET请求,所以我们只需要声明如何获取学科数据以及如何序列化学科数据,前者用`queryset`属性指定,后者用`serializer_class`属性指定。要使用上面的`SubjectView`,需要修改`urls.py`文件,如下所示。

```Python
urlpatterns = [
    path('api/subjects/', SubjectView.as_view()),   
]
```

很显然,上面的做法较之之前讲到的FBV要简单很多。

#### 继承ModelViewSet

如果学科对应的数据接口需要支持GET、POST、PUT、PATCH、DELETE请求来支持对学科资源的获取、新增、更新、删除操作,更为简单的做法是继承`ModelViewSet`来编写学科视图类。再次修改`polls/views.py`文件,去掉`SubjectView`类,添加一个名为`SubjectViewSet`的类,代码如下所示。
J
jackfrued 已提交
32 33 34 35 36 37 38

```Python
class SubjectViewSet(ModelViewSet):
    queryset = Subject.objects.all()
    serializer_class = SubjectSerializer
```

J
jackfrued 已提交
39
通过查看`ModelViewSet`类的源代码可以发现,该类共有6个父类,其中前5个父类分别实现对POST(新增学科)、GET(获取指定学科)、PUT/PATCH(更新学科)、DELETE(删除学科)和GET(获取学科列表)操作的支持,对应的方法分别是`create``retrieve``update``destroy``list`。由于`ModelViewSet`的父类中已经实现了这些方法,所以我们几乎没有编写任何代码就完成了学科数据全套接口的开发,我们要做的仅仅是指出如何获取到数据(通过`queryset`属性指定)以及如何序列化数据(通过`serializer_class`属性指定),这一点跟上面继承`APIView`的子类做法是一致的。
J
jackfrued 已提交
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54

```Python
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
```

J
jackfrued 已提交
55
要使用上面的`SubjectViewSet`,需要在`urls.py`文件中进行URL映射。由于`ModelViewSet`相当于是多个视图函数的汇总,所以不同于之前映射URL的方式,我们需要先创建一个路由器并通过它注册`SubjectViewSet`,然后将注册成功后生成的URL一并添加到`urlspattern`列表中,代码如下所示。
J
jackfrued 已提交
56 57 58 59 60 61 62

```Python
router = DefaultRouter()
router.register('api/subjects', SubjectViewSet)
urlpatterns += router.urls
```

J
jackfrued 已提交
63 64 65 66 67
除了`ModelViewSet`类外,DRF还提供了一个名为`ReadOnlyModelViewSet` 的类,从名字上就可以看出,该类是只读视图的集合,也就意味着,继承该类定制的数据接口只能支持GET请求,也就是获取单个资源和资源列表的请求。

### 数据分页

### 数据筛选
68