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

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



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 装饰器,代码更清晰,功能更强大。
在Django Rest Framework (DRF) 中实现OAuth2.0的前后端分离通常涉及到几个关键步骤。由于这里无法直接给出完整的代码,我会提供一个概述以及关键部分的代码示例。首先,你需要安装`djangorestframework-oauth2_provider`库: ```bash pip install djangorestframework-oauth2_provider ``` 然后,在你的Django项目中配置设置文件,例如`settings.py`: ```python INSTALLED_APPS = [ # ... 'rest_framework', 'oauth2_provider', ] REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'oauth2_provider.contrib.rest_framework.OAuth2Authentication', ), } OAUTH2_PROVIDER = { 'SCOPES': { 'read': 'Read scope', 'write': 'Write scope', } } ``` 创建应用并注册模型: ```python from rest_framework import routers, serializers, viewsets from oauth2_provider.models import Application class ApplicationSerializer(serializers.ModelSerializer): class Meta: model = Application fields = ['client_id', 'client_secret', 'name', 'redirect_uris', 'user'] class ApplicationViewSet(viewsets.ModelViewSet): queryset = Application.objects.all() serializer_class = ApplicationSerializer router = routers.DefaultRouter() router.register(r'applications', ApplicationViewSet) urlpatterns = router.urls ``` 在URL配置中添加OAuth2资源: ```python from django.urls import path, include urlpatterns += [ path('api/', include(router.urls)), path('api/oauth2/', include('oauth2_provider.urls', namespace='oauth2_provider')), ] ``` 对于客户端认证,你可以创建一个视图或前端API请求处理登录: ```python from rest_framework.views import APIView from oauth2_provider.views.authtoken import ObtainAuthToken from rest_framework.response import Response class CustomObtainAuthToken(ObtainAuthToken): def post(self, request, *args, **kwargs): response = super().post(request, *args, **kwargs) user = self.user_cache if user.is_active: # 这里可以增加额外的数据处理或验证 return Response({ 'access_token': response.data['token'], 'user_data': { 'username': user.username, 'email': user.email }, }) else: return Response(response.data, status=status.HTTP_401_UNAUTHORIZED) urlpatterns += [ path('login/token/', CustomObtainAuthToken.as_view(), name='token_obtain_pair'), ] ``` 这只是一个基础的框架,实际项目中你还需要处理授权码、刷新令牌等其他流程,并在后端验证用户权限。同时,前端需要实现相应的逻辑来请求访问令牌和使用它们获取数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZZZ_Tong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值