Django中viewsets.ViewSet与ModelViewSet的适用场景、差异及方法重写疑问
Django REST Framework 3.7: ViewSet vs ModelViewSet 差异、适用场景及
get_object()重写问题 嘿,刚好对DRF 3.7里这两个ViewSet的区别熟得很,我来给你掰扯清楚:
一、ViewSet与ModelViewSet的核心差异
最本质的区别在于默认提供的功能多少和继承链不同:
viewsets.ViewSet:它的父类是APIView,仅提供将视图方法(比如list、create)绑定到路由的能力,但没有任何默认的CRUD动作实现。你得手动编写每个动作的逻辑,或者按需混入对应的Mixin(比如ListModelMixin、CreateModelMixin)来添加特定功能。viewsets.ModelViewSet:它继承自GenericViewSet,同时混入了CreateModelMixin、RetrieveModelMixin、UpdateModelMixin、DestroyModelMixin、ListModelMixin这五个Mixin。这意味着它自带了完整的list、create、retrieve、update、partial_update、destroy动作实现,只要指定queryset和serializer_class,就能直接跑出一套标准的CRUD接口,不用自己写基础逻辑。
二、分别何时使用?
用ModelViewSet的场景:
当你的视图逻辑完全对应单个模型的标准CRUD操作,不需要太多自定义逻辑时,它能帮你省超多代码:
- 简单的资源管理接口(比如用户信息、商品列表、分类管理)
- 快速搭建原型,只需要基础的增删改查功能
- 业务逻辑不复杂,不需要对某个CRUD动作做特殊处理的场景
用ViewSet的场景:
当你需要灵活自定义视图功能时,它是更好的选择:
- 只需要部分CRUD动作(比如只需要
retrieve和list,不需要创建、修改、删除),可以只混入对应的Mixin(比如RetrieveModelMixin+ListModelMixin) - 需要添加非CRUD的自定义动作(比如批量导入数据、发送验证码、生成统计报表),可以自己定义方法并用
@action装饰器标记 - 视图逻辑不依赖单个模型(比如跨多个模型的复杂查询、非数据库相关的操作)
三、关于get_object()方法的重写问题
先纠正个小细节:DRF里的方法是get_object()(单数),不是get_objects()。
- 对于
viewsets.ViewSet:它本身继承自APIView,默认没有get_object()方法,所以不存在“重写”的说法。如果需要类似功能,你要么自己实现这个方法,要么改为继承viewsets.GenericViewSet(它包含get_object()),再按需混入Mixin。 - 对于
viewsets.ModelViewSet:它继承了GenericViewSet,而get_object()正是GenericViewSet提供的方法,所以你完全可以重写它来自定义获取对象的逻辑,比如:def get_object(self): obj = super().get_object() # 自定义逻辑:验证当前用户是否有权限访问该对象 if obj.owner != self.request.user: raise PermissionDenied() return obj
内容的提问来源于stack exchange,提问作者giveJob
相关产品推荐
相关产品推荐

