【问题标题】:Django REST Framework: Generics or ModelViewSets?Django REST 框架:泛型还是模型视图集?
【发布时间】:2014-09-27 08:33:19
【问题描述】:

我为我的 REST API 使用泛型和普通 url,但现在我遇到了一个问题:我想要自定义操作、简单的视图来用我的模型做一些事情,比如“运行”、“发布”等。

ViewSet 提供 action 装饰器来创建自定义操作,但仅在 ViewSets 中,还有逐步路由器,这使我们能够使用 railsish 约定优于配置来简化一切。

但我发现ModelViewSet 为我们提供了与泛型相同的能力:完整的 CRUD、序列化程序、过滤器、自定义前置/后置和查询集,因此,它引发了问题:

如果ModelViewSet 提供相同的能力甚至更多,为什么还有泛型?有什么区别?

【问题讨论】:

    标签: python django rest django-rest-framework


    【解决方案1】:

    不同之处在于它们提供的方法。

    例如:

    GenericViewSet 继承自 GenericAPIView,但不提供任何基本操作的实现。只是只有get_object,get_queryset。

    ModelViewSet 继承自 GenericAPIView 并包含各种操作的实现。换句话说,您不需要实现列表、检索、创建、更新或销毁等基本操作。当然,您可以覆盖它们并实现您自己的列表或您自己的创建方法。

    您可以在 API 参考部分阅读更多相关信息: ModelViewSet

    【讨论】:

    • 我想知道 ModelViewSet 和 ListCreateAPIView 等泛型之间的区别
    • 你问的是 ModelViewSet 和 Generics 有什么区别?
    • 我就是这么说的:)
    • 我编辑了我的答案,请检查一下,但区别是相似的。
    • 如果你只使用GenericViewSet,你需要实现你自己的create、destroy等,而不是如果你使用ModelViewSet,它已经有一个create、destroy、list等方法。
    【解决方案2】:

    GenericsModelViewSet 的区别在于:

    1. 方便
      通常 ModelViewSet 更方便。因为 ModelViewSet 支持使用 DRF 路由器自动创建 url 模式。但 泛型 不会。你自己做。

    2. 短而脆的代码
      如果要创建 CRUD,Generics 需要两个类(ListCreateAPIView 和 RetrieveUpdateDestroyAPIView)。但是ModelViewSet只需要一个类(ModelViewSet)。

    查看下面的声明。两者都继承自GenericAPIViewmixins.CreateModelMixinmixins.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
    

    【讨论】:

    • 如果 ModelViewset 提供了基本 CRUD 操作的选项,为什么我们在声明 ModelViewset 时要继承不同的 mixin 类?
    【解决方案3】:

    如果 ModelViewSet 提供相同的功能甚至更多,为什么还有泛型?

    让我先为你更明确地重新表述一下这个问题......

    “为什么还有通用视图,当也有通用视图集时”

    这实际上只是归结为为什么 REST 框架同时支持视图和视图集的问题。答案 - ViewSets 对于原型设计或 API URL 巧妙地映射到整个固定约定的情况(例如 CRUD 样式 API)很有用。视图对于显式或在您的 URL 没有完全映射到固定约定的情况下很有用。

    【讨论】:

    • 但是GenericAPIViews 也绑定了类似的逻辑,我的意思是,你有ListCreateAPIView(带有 Create 和 List mixins),它应该分配给一个 url,所以它有一些约定。但是你可以对ViewSet 做同样的事情,只需继承 Create 和 List mixins。但是,使用 APIView,您必须使用 post 来创建和获取列表。使用 ViewSet,您可以使用 to_view 方法的参数将不同的操作绑定到不同的请求。所以,ViewSet 看起来更灵活......但是,是的,有 router,它使“约定”并且仅适用于 ViewSets。也许我错过了什么?
    • 哦,好吧,源码回答了所有问题:ModelViewSet 继承了 GenericAPIView。因此,GenericAPIView 类提供了覆盖 post/get/put/delete 请求视图的能力。它使用mixins并将post分配给createget分配给list等。问题是:例如listretrieve使用get,所以我们不能混合它GenericAPIView。但是,有ViewSet,它可以覆盖actions,而不是http 请求类型(POST、GET、PUT)视图。如我所见,这是主要的意识形态差异,是吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-09-04
    • 2017-03-27
    • 2018-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-04
    相关资源
    最近更新 更多