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.ModelViewSet
和 APIView
是 Django REST Framework (DRF) 中用于构建 API 视图的两个重要类。它们有相似之处,但也有明显的区别。以下是它们的区别与联系:
1. 联系
- 共同点:
- 两者都用于处理 HTTP 请求(如
GET
、POST
、PUT
、DELETE
等)。 - 都基于 DRF 的视图类体系,继承了
rest_framework.views.APIView
或其子类。 - 都可以用于实现 RESTful API。
- 两者都用于处理 HTTP 请求(如
2. 区别
特性 | APIView | ModelViewSet |
---|---|---|
用途 | 用于实现自定义逻辑的视图。 | 用于快速实现基于模型的 CRUD 操作。 |
代码量 | 需要手动编写更多的代码(如 get 、post 等方法)。 | 代码量较少,默认实现了 CRUD 操作。 |
灵活性 | 更灵活,适合需要自定义逻辑的场景。 | 灵活性较低,适合标准化的 CRUD 操作。 |
默认方法 | 需要手动实现所有 HTTP 方法(如 get 、post 等)。 | 默认实现了 list 、create 、retrieve 、update 、destroy 等方法。 |
适用场景 | 适用于非标准逻辑或复杂业务场景。 | 适用于标准的模型 CRUD 操作。 |
路由配置 | 需要手动配置路由。 | 可以与 DefaultRouter 或 SimpleRouter 配合,自动生成路由。 |
性能 | 性能取决于自定义逻辑。 | 性能较好,因为默认方法经过优化。 |
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)
- 特点:
- 需要手动实现
get
、post
等方法。 - 适合需要自定义逻辑的场景。
- 需要手动实现
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
- 特点:
- 默认实现了
list
、create
、retrieve
、update
、destroy
等方法。 - 适合标准的 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. 小结
选择依据 | APIView | ModelViewSet |
---|---|---|
是否需要自定义逻辑 | 是 | 否 |
是否需要快速实现 CRUD | 否 | 是 |
是否需要自动生成路由 | 否 | 是 |
- 如果需要快速实现标准的 CRUD 操作,推荐使用
ModelViewSet
。 - 如果需要实现复杂的业务逻辑或非标准操作,推荐使用
APIView
。
APIView如何自定义多个接口
在 APIView
中,默认情况下每个 HTTP 方法(如 GET
、POST
、PUT
等)只能定义一个对应的处理函数(如 get
、post
、put
等)。如果你需要在同一个 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
装饰器,代码更清晰,功能更强大。