当前位置: 首页 > news >正文

DRF框架中viewsets.ModelViewSet、APIView区别与联系

DRF框架中viewsets.ModelViewSet、APIView区别与联系


文章目录

  • DRF框架中viewsets.ModelViewSet、APIView区别与联系
    • 1. 联系
    • 2. 区别
    • 3. 使用示例
      • APIView 示例
      • ModelViewSet 示例
    • 4. 路由配置
      • APIView 的路由
      • ModelViewSet 的路由
    • 5. 小结
    • APIView如何自定义多个接口
      • 方法 1:在 URL 中区分不同的操作
        • 示例代码
        • 请求示例
      • 方法 2:使用不同的 URL 路径
        • 示例代码
        • 路由配置
        • 请求示例
      • 方法 3:使用 `@action` 装饰器(推荐)
        • 示例代码
        • 路由配置
        • 请求示例
    • **总结**


viewsets.ModelViewSetAPIView 是 Django REST Framework (DRF) 中用于构建 API 视图的两个重要类。它们有相似之处,但也有明显的区别。以下是它们的区别与联系:


1. 联系

  • 共同点
    • 两者都用于处理 HTTP 请求(如 GETPOSTPUTDELETE 等)。
    • 都基于 DRF 的视图类体系,继承了 rest_framework.views.APIView 或其子类。
    • 都可以用于实现 RESTful API。

2. 区别

特性APIViewModelViewSet
用途用于实现自定义逻辑的视图。用于快速实现基于模型的 CRUD 操作。
代码量需要手动编写更多的代码(如 getpost 等方法)。代码量较少,默认实现了 CRUD 操作。
灵活性更灵活,适合需要自定义逻辑的场景。灵活性较低,适合标准化的 CRUD 操作。
默认方法需要手动实现所有 HTTP 方法(如 getpost 等)。默认实现了 listcreateretrieveupdatedestroy 等方法。
适用场景适用于非标准逻辑或复杂业务场景。适用于标准的模型 CRUD 操作。
路由配置需要手动配置路由。可以与 DefaultRouterSimpleRouter 配合,自动生成路由。
性能性能取决于自定义逻辑。性能较好,因为默认方法经过优化。

3. 使用示例

APIView 示例

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import MyModel
from .serializers import MyModelSerializer

class MyModelAPIView(APIView):
    def get(self, request, *args, **kwargs):
        my_models = MyModel.objects.all()
        serializer = MyModelSerializer(my_models, many=True)
        return Response(serializer.data)

    def post(self, request, *args, **kwargs):
        serializer = MyModelSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
  • 特点
    • 需要手动实现 getpost 等方法。
    • 适合需要自定义逻辑的场景。

ModelViewSet 示例

from rest_framework import viewsets
from .models import MyModel
from .serializers import MyModelSerializer

class MyModelViewSet(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer
  • 特点
    • 默认实现了 listcreateretrieveupdatedestroy 等方法。
    • 适合标准的 CRUD 操作。

4. 路由配置

APIView 的路由

from django.urls import path
from .views import MyModelAPIView

urlpatterns = [
    path('mymodels/', MyModelAPIView.as_view(), name='mymodel-list'),
]

ModelViewSet 的路由

from rest_framework.routers import DefaultRouter
from .views import MyModelViewSet

router = DefaultRouter()
router.register(r'mymodels', MyModelViewSet)

urlpatterns = router.urls
  • 特点
    • ModelViewSet 可以与 DefaultRouter 配合,自动生成路由(如 /mymodels//mymodels/<id>/ 等)。
    • APIView 需要手动配置路由。

5. 小结

选择依据APIViewModelViewSet
是否需要自定义逻辑
是否需要快速实现 CRUD
是否需要自动生成路由
  • 如果需要快速实现标准的 CRUD 操作,推荐使用 ModelViewSet
  • 如果需要实现复杂的业务逻辑或非标准操作,推荐使用 APIView

APIView如何自定义多个接口

APIView 中,默认情况下每个 HTTP 方法(如 GETPOSTPUT 等)只能定义一个对应的处理函数(如 getpostput 等)。如果你需要在同一个 APIView 中定义多个 POST 接口,可以通过以下两种方式实现:


方法 1:在 URL 中区分不同的操作

通过 URL 路径参数或查询参数来区分不同的 POST 操作,然后在 post 方法中根据参数调用不同的逻辑。

示例代码
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

class MyModelAPIView(APIView):
    def post(self, request, *args, **kwargs):
        action = request.data.get('action')  # 通过请求体中的参数区分操作
        if action == 'create':
            return self.create_model(request)
        elif action == 'update':
            return self.update_model(request)
        else:
            return Response({'error': 'Invalid action'}, status=status.HTTP_400_BAD_REQUEST)

    def create_model(self, request):
        # 处理创建逻辑
        return Response({'message': 'Model created'}, status=status.HTTP_201_CREATED)

    def update_model(self, request):
        # 处理更新逻辑
        return Response({'message': 'Model updated'}, status=status.HTTP_200_OK)
请求示例
  • 创建操作:

    POST /mymodels/
    Content-Type: application/json
    
    {
        "action": "create",
        "name": "New Model"
    }
    
  • 更新操作:

    POST /mymodels/
    Content-Type: application/json
    
    {
        "action": "update",
        "id": 1,
        "name": "Updated Model"
    }
    

方法 2:使用不同的 URL 路径

通过定义不同的 URL 路径来区分不同的 POST 操作,然后在 APIView 中使用不同的方法处理。

示例代码
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

class MyModelCreateAPIView(APIView):
    def post(self, request, *args, **kwargs):
        # 处理创建逻辑
        return Response({'message': 'Model created'}, status=status.HTTP_201_CREATED)

class MyModelUpdateAPIView(APIView):
    def post(self, request, *args, **kwargs):
        # 处理更新逻辑
        return Response({'message': 'Model updated'}, status=status.HTTP_200_OK)
路由配置
from django.urls import path
from .views import MyModelCreateAPIView, MyModelUpdateAPIView

urlpatterns = [
    path('mymodels/create/', MyModelCreateAPIView.as_view(), name='mymodel-create'),
    path('mymodels/update/', MyModelUpdateAPIView.as_view(), name='mymodel-update'),
]
请求示例
  • 创建操作:

    POST /mymodels/create/
    Content-Type: application/json
    
    {
        "name": "New Model"
    }
    
  • 更新操作:

    POST /mymodels/update/
    Content-Type: application/json
    
    {
        "id": 1,
        "name": "Updated Model"
    }
    

方法 3:使用 @action 装饰器(推荐)

如果你使用的是 ViewSet 而不是 APIView,可以使用 DRF 的 @action 装饰器来定义多个 POST 接口。

示例代码
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import status

class MyModelViewSet(viewsets.ViewSet):
    @action(detail=False, methods=['post'])
    def create_model(self, request):
        # 处理创建逻辑
        return Response({'message': 'Model created'}, status=status.HTTP_201_CREATED)

    @action(detail=False, methods=['post'])
    def update_model(self, request):
        # 处理更新逻辑
        return Response({'message': 'Model updated'}, status=status.HTTP_200_OK)
路由配置
from rest_framework.routers import DefaultRouter
from .views import MyModelViewSet

router = DefaultRouter()
router.register(r'mymodels', MyModelViewSet, basename='mymodel')

urlpatterns = router.urls
请求示例
  • 创建操作:

    POST /mymodels/create_model/
    Content-Type: application/json
    
    {
        "name": "New Model"
    }
    
  • 更新操作:

    POST /mymodels/update_model/
    Content-Type: application/json
    
    {
        "id": 1,
        "name": "Updated Model"
    }
    

总结

  • 方法 1:适合简单的场景,通过请求参数区分不同操作。
  • 方法 2:适合需要明确分离不同操作的场景,通过 URL 路径区分。
  • 方法 3:推荐使用 ViewSet@action 装饰器,代码更清晰,功能更强大。

相关文章:

  • 八大元素定位
  • TRELLIS 部署笔记
  • 高速硬件电路设计
  • 基于阿里云调用deepseek大模型
  • 如何搭建同城O2O服务平台?AI外卖跑腿APP技术革新与开发实践
  • 【Java基础】Java数组
  • 深圳SMT贴片加工厂家核心技术及服务优势解析
  • mybatis使用typeHandler实现类型转换
  • elabradio入门第三讲——PSK传输系统的载波同步
  • maya创建文字模型
  • 深入理解 Java 反射机制:获取类信息与动态操作
  • Windows 环境下 Grafana 安装指南
  • C++接口继承和实现继承
  • 观察者模式原理详解以及Spring源码如何使用观察者模式?
  • ChatGLM
  • 前端函数在开发环境与生产环境中处理空字符串的差异及解决方案
  • 为什么WP建站更适合于谷歌SEO优化?
  • Mathtype安装入门指南
  • WPF9-数据绑定进阶
  • 基于 GEE 的 2019 - 2024 年研究区大气污染物浓度月度变化趋势(CO、NO₂、SO₂、O₃ 、HCHO)
  • 西藏日喀则市拉孜县发生5.5级地震,震源深度10公里
  • “80后”李灿已任重庆市南川区领导,此前获公示拟提名为副区长人选
  • “犍陀罗艺术与亚洲文明”在浙大对外展出
  • 匈牙利史专家阚思静逝世,享年87岁
  • 佩斯科夫:俄会考虑30天停火提议,但试图对俄施压无用
  • 王毅同巴基斯坦副总理兼外长达尔通电话