Appearance
通过前几章的折腾,我们已经把文章增删改查都完成了。经过合理运用类和继承的理念,代码已经相当精简了。但是, DRF 框架提供了更高层的抽象,可以让代码量进一步的减少。
来看看视图集的威力吧。
重构代码
大部分对接口的操作,都是在增删改查的基础上衍生出来的。既然这样,视图集就将这些通用操作集成在一起了。
试下用视图集重构代码。
首先将之前写的与文章有关的序列化器都注释掉,新增一个提供给视图集的新序列化器:
python
# article/serializers.py
...
class ArticleSerializer(serializers.HyperlinkedModelSerializer):
author = UserDescSerializer(read_only=True)
class Meta:
model = Article
fields = '__all__'
...
序列化器继承的 HyperlinkedModelSerializer
基本上与之前用的 ModelSerializer
差不多,区别是它自动提供了外键字段的超链接,并且默认不包含模型对象的 id 字段。
接着把之前写的文章视图也全注释掉,并新增代码:
python
# article/views.py
...
from rest_framework import viewsets
from article.serializers import ArticleSerializer
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
permission_classes = [IsAdminUserOrReadOnly]
def perform_create(self, serializer):
serializer.save(author=self.request.user)
视图集类把前面章节写的列表、详情等逻辑都集成到一起,并且提供了默认的增删改查的实现。
这些基础逻辑都在父类
ModelViewSet
里封装实现了,有兴趣可耐心研究源码。
perform_create()
跟之前一样,在创建文章前,提供了视图集无法自行推断的用户外键字段。
由于使用了视图集,我们甚至连路由都不用自己设计了,使用框架提供的 Router
类就可以自动处理视图和 url 的连接。
修改项目根路由:
python
# drf_vue_blog/urls.py
...
from rest_framework.routers import DefaultRouter
from article import views
router = DefaultRouter()
router.register(r'article', views.ArticleViewSet)
urlpatterns = [
...
# drf 自动注册路由
path('api/', include(router.urls)),
# article/urls.py 可以全注释掉,不需要了
# path('api/article/', include('article.urls', namespace='article')),
]
最后为了让分页更准确,给模型类规定好查询排序:
python
# article/models.py
...
# 已经有的博客文章 model
class Article(models.Model):
...
class Meta:
ordering = ['-created']
完成了。
平复下心情,烧两柱香,抱着试一试的心态打开命令行:(或浏览器)
python
C:\...> http http://127.0.0.1:8000/api/
HTTP/1.1 200 OK
...
{
"article": "http://127.0.0.1:8000/api/article/"
}
Router
类送给我们一个接口导航!
顺着导航里给的链接再试试:
python
C:\...> http http://127.0.0.1:8000/api/article/
HTTP/1.1 200 OK
...
{
"count": 5,
"next": "http://127.0.0.1:8000/api/article/?page=2",
"previous": null,
"results": [
{
...
},
...
]
}
正确的显示了列表。再顺着列表提供的详情页点进去也肯定是没问题的。权限控制也与之前的完全一样。
就这么几行代码,就完成了一整套的接口操作!
鱼和熊掌
视图集最大程度地减少需要编写的代码量,并允许你专注于 API 提供的交互和表示形式,而不是 URL 的细节。但并不意味着用它总是比构建单独的视图更好。
原因就是它的抽象程度太高了。如果你对 DRF 框架的理解不深并且需要做某种定制化业务,可能让你一时间无从下手。
在精简和可读之间,你应该根据实际情况进行取舍。
附加题
前几章用普通视图分别实现了列表和详情接口,并且不同的接口对应了不同的序列化器。
虽然视图集默认只提供一个序列化器,但是通过覆写 get_serializer_class()
方法可以根据条件而访问不同的序列化器:
python
class ArticleViewSet(viewsets.ModelViewSet):
...
def get_serializer_class(self):
if self.action == 'list':
return SomeSerializer
else:
return AnotherSerializer
教程这里就暂时不去覆写了,后面有需要再来修改。
看到这里恭喜你,你已经把 DRF 基础的功能都体验完了,官方提供的入门教程也学完了。接下来的章节就是继续完善各类接口,并且熟悉框架提供的各类细节功能了。