DRF框架视图view相关

继承关系图(文字版+结构图)


🔹 继承关系

APIView
   ↑
GenericAPIView
   ↑
+ Mixins (ListModelMixin, CreateModelMixin, etc.)
   ↑
ViewSet (ModelViewSet, ReadOnlyModelViewSet)

🔹 详细说明

  1. APIView
    • 基础类,封装了 request/response/exception,类似 Django 的 View
    • 不绑定模型,完全自定义逻辑。
  2. GenericAPIView
    • 在 APIView 基础上扩展:
      • queryset
      • serializer_class
      • 提供 get_queryset()get_object()get_serializer() 等。
    • 更适合和模型打交道。
  3. Mixin 系列
    • 把通用操作做成小模块,可以自由组合:
      • ListModelMixin → 列表
      • CreateModelMixin → 新增
      • RetrieveModelMixin → 获取单个
      • UpdateModelMixin → 更新
      • DestroyModelMixin → 删除
  4. ViewSet / ModelViewSet
    • GenericAPIView + Mixins 封装在一起。
    • ModelViewSet = 增删改查全家桶。
    • 可以和 router 配合自动生成 url

🔹 总结

  • APIView:最基础的类视图,自己实现逻辑。
  • GenericAPIView:在 APIView 基础上扩展,和模型绑定,支持 queryset / serializer。
  • Mixins:把常用 CRUD 封装成小块。
  • ViewSet:= GenericAPIView + Mixins,大多数业务接口首选。

从 APIView 到 ModelViewSet 的完整进化示例

写一个 同一个业务接口(EnterpriseInfo 列表+详情),分别用 APIView → GenericAPIView → GenericAPIView+Mixins → ModelViewSet 来实现。


🟢 版本1:APIView(完全手写)

# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from core.enterprise.models import EnterpriseInfo
from core.enterprise.serializers import EnterpriseInfoSerializer

class EnterpriseInfoAPIView(APIView):
    def get(self, request, pk=None):
        if pk:
            obj = EnterpriseInfo.objects.get(pk=pk)
            serializer = EnterpriseInfoSerializer(obj)
            return Response(serializer.data)
        else:
            queryset = EnterpriseInfo.objects.all()
            serializer = EnterpriseInfoSerializer(queryset, many=True)
            return Response(serializer.data)

    def post(self, request):
        serializer = EnterpriseInfoSerializer(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)

🟡 版本2:GenericAPIView(提供 querysetserializer_class

from rest_framework.generics import GenericAPIView

class EnterpriseInfoGenericAPIView(GenericAPIView):
    queryset = EnterpriseInfo.objects.all()
    serializer_class = EnterpriseInfoSerializer

    def get(self, request, pk=None):
        if pk:
            obj = self.get_object()
            serializer = self.get_serializer(obj)
        else:
            queryset = self.get_queryset()
            serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

👉 这里不用写 EnterpriseInfo.objects.get,而是用 get_queryset()get_object()get_serializer()


🟠 版本3:GenericAPIView + Mixins(组合常见操作)

from rest_framework import mixins

class EnterpriseInfoListCreateView(mixins.ListModelMixin,
                                   mixins.CreateModelMixin,
                                   GenericAPIView):
    queryset = EnterpriseInfo.objects.all()
    serializer_class = EnterpriseInfoSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)


class EnterpriseInfoDetailView(mixins.RetrieveModelMixin,
                               mixins.UpdateModelMixin,
                               mixins.DestroyModelMixin,
                               GenericAPIView):
    queryset = EnterpriseInfo.objects.all()
    serializer_class = EnterpriseInfoSerializer

    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

🔴 版本4:ModelViewSet(最终形态)

from rest_framework import viewsets

class EnterpriseInfoViewSet(viewsets.ModelViewSet):
    queryset = EnterpriseInfo.objects.all()
    serializer_class = EnterpriseInfoSerializer

然后 urls.py

from rest_framework.routers import DefaultRouter
from core.enterprise.views import EnterpriseInfoViewSet

router = DefaultRouter()
router.register(r'enterprise', EnterpriseInfoViewSet)

urlpatterns = router.urls

📌 总结

  • APIView:最基础,灵活但代码重复。
  • GenericAPIView:提供了 queryset / serializer_class,减少重复。
  • GenericAPIView + Mixins:常见 CRUD 用 mixins 封装,进一步简化。
  • ModelViewSet:全家桶,一行代码搞定,配合 router 自动生成 URL。

对照表,展示 APIView、GenericAPIView、GenericAPIView+Mixins、ModelViewSet 的差异,你背下来就能在面试里直接说。


🔑 Django REST Framework 四种写法对比

写法代码量特点适用场景缺点
APIView代码最多直接继承 APIView,所有逻辑手写(get/post/put/delete灵活的自定义接口(如大屏统计、复杂计算)代码重复,容易冗余
GenericAPIView代码少一些提供 querysetserializer_class,内置 get_queryset()get_object()get_serializer()需要标准化 CRUD,但还要定制逻辑依旧要手写 HTTP 方法
GenericAPIView + Mixins代码更少通过 ListModelMixin / CreateModelMixin / UpdateModelMixin 等组合,直接用 list/create/update/destroy 方法典型的 REST API CRUD方法命名受限,灵活性下降
ModelViewSet最少(几行搞定)自带 增删改查,配合 router 自动生成 URL,企业开发最常见常规的表管理、后台 CRUD API复杂接口(统计、大屏)不适合

📌 示例对比(以 EnterpriseInfo 为例)

写法get 列表get 单条post 创建
APIView手写 EnterpriseInfo.objects.all() + serializer = Serializer(...)手写 get(pk)手写校验、保存
GenericAPIViewself.get_queryset()self.get_object()self.get_serializer(data=...)
GenericAPIView + Mixinsself.list()self.retrieve()self.create()
ModelViewSet自动生成自动生成自动生成

面试套路(推荐你记住这一句话):

“在 DRF 里,开发接口有四层封装:

  • APIView 最原始,全部手写,灵活但冗余。
  • GenericAPIView 提供了 querysetserializer_class,减少重复。
  • 再结合 Mixins,就能快速实现 CRUD。
  • ModelViewSet 是最高级别封装,配合 router 一行代码搞定增删改查。
    通常后台 CRUD 用 ModelViewSet,而大屏统计、非标准接口还是会用 APIView。”

Scroll to Top