Django REST framework 源码剖析-视图集详解(ViewSet)

Django REST framework视图图解

  • 视图类(View)

‌视图‌是DRF中处理用户请求的基本单元。它们可以是函数视图(FBV)或类视图(CBV)。函数视图使用函数来处理请求,而类视图则使用类来处理请求。类视图默认会自动dispatch特定的HTTP方法,如GET、POST等,不需要像函数视图那样通过单独的条件判断来处理不同的HTTP方法。此外,类视图可以使用面向对象的技术,如Mixin(多继承、混用),将代码拆解成可复用的组件‌,GenericAPIView可以与ListModelMixin、CreateModelMixin、RetrieveModelMixin、UpdateModelMixin、DestroyModelMixin等Mixin结合使用,以实现增删改查等功能‌。

  • 视图集(ViewSet)

‌视图集‌是DRF中用于组织相关视图的集合。它们继承自APIView或GenericAPIView,并且可以定义多个方法(如list、create、retrieve、update、destroy等),这些方法对应不同的HTTP请求。视图集可以解决路由匹配和合并的问题,并且方法名可以自定义,路由匹配规则也需要相应修改。视图集还可以与Mixin结合使用,以实现更复杂的业务逻辑‌。

视图集 ViewSet

  • 使用视图集ViewSet,可以将一系列逻辑相关的动作放到一个类中
  • ViewSet视图集类不再实现get()、post()等方法,而是实现动作 action 如 list() 、create() 等
  • 视图集只在使用as_view()方法的时候,才会将action动作与具体请求方式对应上

动作 action

  • list() 提供一组数据
  • retrieve() 提供单个数据(详情)
  • create() 创建数据
  • update() 保存数据
  • destory() 删除数据

常用视图集父类 ViewSet

  • 继承自APIView与ViewSetMixin,作用也与APIView基本类似,提供了身份认证、权限校验、流量管理等
  • ViewSet主要通过继承ViewSetMixin来实现在调用as_view()时传入字典(如{'get':'list'})的映射处理工作
  • 在ViewSet中,没有提供任何动作action方法,需要我们自己实现action方法

视图示例

python 复制代码
from rest_framework.response import Response
from rest_framework import viewsets
from myproject.models import BookInfo
from myproject.serializer import BookInfoSerializer


class BookInfoViewSet(viewsets.ViewSet):

    def list(self, request):
        books = BookInfo.objects.all()
        serializer = BookInfoSerializer(books, many=True)
        return Response(serializer.data)

    def retrieve(self, request, pk=None):
        try:
            books = BookInfo.objects.get(id=pk)
        except BookInfo.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)
        serializer = BookInfoSerializer(books)
        return Response(serializer.data)

路由示例

python 复制代码
from django.urls import path, re_path
from myproject.viewsets import BookInfoViewSet


urlpatterns = [
    url(r'^books/$', BookInfoViewSet.as_view({'get':'list'}),
    url(r'^books/(?P<pk>\d+)/$', BookInfoViewSet.as_view({'get': 'retrieve'})
]

常用视图集父类 GenericViewSet

  • 使用ViewSet通常并不方便,因为list、retrieve、create、update、destory等方法都需要自己编写,而这些方法与前面讲过的Mixin扩展类提供的方法同名,所以我们可以通过继承Mixin扩展类来复用这些方法而无需自己编写,但是Mixin扩展类依赖与GenericAPIView,所以还需要继承GenericAPIView
  • GenericViewSet就帮助我们完成了这样的继承工作,继承自GenericAPIView与ViewSetMixin,在实现了调用as_view()时传入字典(如{'get':'list'})的映射处理工作的同时,还提供了GenericAPIView提供的基础方法,可以直接搭配Mixin扩展类使用

视图示例

python 复制代码
from rest_framework.viewsets import GenericViewSet
from rest_framework.mixins import ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin


class EmployeeViewSet(GenericViewSet,ListModelMixin,CreateModelMixin,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
    queryset = Student.objects.all()
    serializer_class = StudentModelSerializer

路由示例

python 复制代码
from django.urls import path, re_path
from myproject import views


urlpatterns = [
    path("employee/", views.EmployeeViewSet.as_view({"get": "list", "post": "create"})),
    re_path("employee/(?P<pk>\d+)/", views.EmployeeViewSet.as_view({"get": "retrieve","put":"update","delete":"destroy"})),
]

常用视图集父类 ModelViewSet

  • 继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin、CreateModelMixin、UpdateModelMixin、DestoryModelMixin

视图示例

python 复制代码
from rest_framework.viewsets import ModelViewSet
from myproject.models import Book
from myproject.serializer import BookSerializer


class CustomModelViewSet(ModelViewSet):
    """
    list:获取列表数据
    retrieve:获取详情数据
    crate:新增数据
    update:更新信息
    DELETE:删除
    """
    queryset = Book.objects.all()
    serializer_class = BookSerilizer

路由示例

python 复制代码
from django.urls import path, re_path
from myproject import views


urlpatterns = [
    path("employee_model/", views.CustomModelViewSet.as_view({"get": "list", "post": "create"})),
    re_path("employee_model/(?P<pk>\d+)/", views.CustomModelViewSet.as_view({"get": "retrieve","put":"update","delete":"destroy"})),
]

常用视图集父类 ReadOnlyModelViewSet

  • 继承自GenericViewSet,同时包括了ListModelMixin、RetrieveModelMixin

视图示例

python 复制代码
from rest_framework.viewsets import ReadOnlyModelViewSet
from myproject.models import Book
from myproject.serializer import BookSerilizer


class CustomReadOnlyModelViewSet(ReadOnlyModelViewSet):
    """
    list:获取列表数据
    retrieve:获取详情数据
    """
    queryset = Book.objects.all()
    serializer_class = BookSerilizer

路由示例

python 复制代码
from django.urls import path, re_path
from myproject import views


urlpatterns = [
    path("employee_readonly/", views.CustomReadOnlyModelViewSet.as_view({"get": "list", "post": "create"})),
    re_path("employee_readonly/(?P<pk>\d+)/", views.CustomReadOnlyModelViewSet.as_view({"get": "retrieve","put":"update","delete":"destroy"})),
]

视图集中自定义附加action动作

视图示例

python 复制代码
from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet
from rest_framework.response import Response
from myproject.models import Employee
from myproject.serializer import EmployeeModelSerializer


class EmployeeModelViewSet(ModelViewSet):
    queryset = Employee.objects.all()
    serializer_class = EmployeeModelSerializer

    def login(self,request):
        """登录功能"""
        return Response({"message":"登录成功"})

路由示例

python 复制代码
from django.urls import path, re_path
from myproject import views


urlpatterns = [
    path("employee_action/", views.StudentModelViewSet.as_view({"get": "list", "post": "create"})),
    re_path("employee_action/(?P<pk>\d+)/", views.StudentModelViewSet.as_view({"get": "retrieve", "put": "update", "delete": "destroy"})),
    path("employee_action/login/",views.StudentModelViewSet.as_view({"get":"login"}))
]

视图集中action属性

  • 在视图集中,我们可以通过action对象属性来获取当前请求视图集时的action动作是哪个

视图示例

python 复制代码
from rest_framework.viewsets import ModelViewSet
from employee.models import Employee
from .serializers import EmployeeModelSerializer
from rest_framework.response import Response


class StudentModelViewSet(ModelViewSet):
    queryset = Employee.objects.all()
    serializer_class = EmployeeModelSerializer

    def get_top_5(self,request):
        """获取前5条信息"""
        # 获取本次请求的视图方法名
        print(self.action) 

路由示例

python 复制代码
from django.urls import path, re_path
from myproject import views


urlpatterns = [
	path("employee/get_top5/",views.StudentModelViewSet.as_view({"get":"get_top_5"}))
]

总结

两个基类

  • ViewSet: 继承ViewSetMixin和APIView
  • GenericViewSet: 继承ViewSetMixin, generics.GenericAPIView
  • ViewSetMixin: 重写了as_view

两个拓展类

  • ModelViewSet: 继承mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,mixins.ListModelMixin,GenericViewSet
  • ReadOnlyModelViewSet:继承mixins.RetrieveModelMixin,mixins.ListModelMixin,GenericViewSet
相关推荐
子兮曰2 天前
jev-ultrafast 深度解析:7 秒订机票的浏览器 Agent 是如何炼成的
前端·后端·agent
子兮曰2 天前
Jev 爆发一周:7 秒 Agent 背后的 System One 生态与三场争议
前端·后端·ai编程
默_笙2 天前
🍙 给每个请求过安检:FastAPI 是怎么把校验写进类型注解的
python
爱勇宝2 天前
ZCode 开源 24 小时:一份没有历史的账本,回答不了"有没有偷代码"
前端·后端·chatglm (智谱)
qq_426003962 天前
启动playwright录制codegen生成自动化测试脚本
python·自动化
千里马学框架2 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
虎头金猫2 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
胡写代码2 天前
别再前后端各写一套表单校验了
java·后端
长沙三为智能科技2 天前
家政小程序开发从0到上线:五阶段交付流程与验收清单
python
伞伞悦读2 天前
【第38期】Python 模块与包详解:import、from、模块搜索路径、包结构和 __init__
开发语言·python