Django REST Framework:使用通用视图还是模型视图集?
我在使用通用类和普通网址来做我的REST API,但现在遇到了一个问题:我想要一些自定义操作,比如简单的视图来对我的模型进行一些操作,比如“运行”、“发布”等。
ViewSet
提供了一个action
装饰器,可以用来创建自定义操作,但这个功能只在ViewSets中可用。此外,还有一些特殊的路由器,可以让我们通过约定优于配置的方式来简化一切,类似于Rails框架。
不过我发现ModelViewSet
也提供了和通用类一样的功能:完整的增删改查(CRUD)、序列化、过滤器、自定义的前后处理和查询集,这就引出了一个问题:
既然ModelViewSet
提供了相同甚至更多的功能,那通用类还有什么用呢?它们之间有什么区别呢?
4 个回答
ModelViewSet可以和路由器一起使用,这样你就不需要自己去设置网址了。而如果使用GenericAPIView,你就得为每一种HTTP方法单独定义网址。
为什么会有泛型(Generics),如果ModelViewSet提供了相同的功能和更多的功能呢?
让我先把这个问题说得更清楚一点...
“既然有了泛型视图,为什么还需要泛型视图集(ViewSets)?”
其实这就是在问,为什么REST框架同时支持视图和视图集。答案是:视图集在快速开发原型或者当你的API网址遵循固定规则时非常有用(比如CRUD风格的API)。而视图则适合在需要明确表达时使用,或者当你的网址不遵循固定规则时使用。
关于Generics和ModelViewSet的区别如下:
方便性
通常来说,ModelViewSet更方便。因为ModelViewSet可以通过DRF路由自动生成网址模式,而Generics就不能,需要你自己来做。代码简洁
如果你想创建CRUD(增删改查),使用Generics需要两个类(ListCreateAPIView和RetrieveUpdateDestroyAPIView)。而ModelViewSet只需要一个类(ModelViewSet)。
下面的声明可以看看。两者都是从GenericAPIView和mixins.CreateModelMixin、mixins.ListModelMixin继承而来的,基本上提供了相同的功能。选择哪个主要看你的个人喜好。不过我在大多数情况下通常会使用ViewSet。
声明
# Generics __________________________________
class ListCreateAPIView(mixins.ListModelMixin,
mixins.CreateModelMixin,
GenericAPIView):
# ModelViewSet _____________________________
class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
# GenericViewSet _____________________________
class GenericViewSet(ViewSetMixin, generics.GenericAPIView):
示例代码
# Generics __________________________________
from rest_framework import generics
class BookList(generics.ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
# ModelViewSet _____________________________
from rest_framework import viewsets
class BookViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
这两者的区别在于它们提供了哪些方法。
举个例子:
GenericViewSet 是从 GenericAPIView 继承而来的,但它并没有提供基本操作的具体实现。它只提供了 get_object 和 get_queryset 这两个方法。
ModelViewSet 也是从 GenericAPIView 继承而来的,但它包含了多种操作的具体实现。换句话说,你不需要自己去实现基本的操作,比如列出数据、获取单个数据、创建数据、更新数据或删除数据。当然,你也可以重写这些方法,自己实现你想要的列出或创建数据的方法。
想了解更多,可以查看 API 参考部分: ModelViewSet