自学内容网 自学内容网

Django REST框架:ModelViewSet全面解析

介绍 Django REST framework (DRF) 中的 viewsets.ModelViewSet,包括其作用、继承关系、默认提供的功能、常见使用方式、适用场景,以及如何在项目架构中正确组织。


1. 什么是 ModelViewSet

Django REST framework (DRF) 中,viewsets.ModelViewSet 是一个视图集 (ViewSet),它自动整合了常见的 CRUD 操作(增删改查),基于指定的 模型 (Model)序列化器 (Serializer),大幅减少了样板代码。

也就是说,如果你要为某个模型提供完整的 RESTful API(列表、详情、创建、修改、删除),只需要写一个 ModelViewSet,再通过 router 自动生成 URL,就能完成。


2. 继承关系

ModelViewSet 的继承关系如下:

class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
    pass

拆解:

  • Mixins

    • CreateModelMixin → 提供 create() 方法 → POST /resources/
    • RetrieveModelMixin → 提供 retrieve() 方法 → GET /resources/{pk}/
    • UpdateModelMixin → 提供 update() / partial_update() 方法 → PUT/PATCH /resources/{pk}/
    • DestroyModelMixin → 提供 destroy() 方法 → DELETE /resources/{pk}/
    • ListModelMixin → 提供 list() 方法 → GET /resources/
  • GenericViewSet

    • 提供了 get_queryset()get_serializer_class() 等通用功能
    • 结合上面的 Mixins,最终形成一个完整的 CRUD API。

3. 默认提供的 API 行为

如果你写了一个 ModelViewSet,并注册到 router 中,你自动获得如下 RESTful API:

方法URL动作Mixin
GET/objects/列表查询ListModelMixin
POST/objects/创建数据CreateModelMixin
GET/objects/{pk}/获取单条数据RetrieveModelMixin
PUT/objects/{pk}/更新整条数据UpdateModelMixin
PATCH/objects/{pk}/部分更新数据UpdateModelMixin
DELETE/objects/{pk}/删除数据DestroyModelMixin

4. 使用示例

示例模型

# models.py
from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=50)
    published_date = models.DateField()
    price = models.DecimalField(max_digits=6, decimal_places=2)

示例序列化器

# serializers.py
from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'

示例 ViewSet

# views.py
from rest_framework import viewsets
from .models import Book
from .serializers import BookSerializer

class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

路由注册

# urls.py
from rest_framework.routers import DefaultRouter
from .views import BookViewSet

router = DefaultRouter()
router.register(r'books', BookViewSet)

urlpatterns = router.urls

这样,你就自动获得了 /books//books/{id}/ 的完整 CRUD API。


BookViewSet API 方法总览表

方法名HTTP 方法URL 格式来源作用说明
list(self, request)GET/books/ListModelMixin获取所有书籍的列表(可分页、可过滤、可排序)
create(self, request)POST/books/CreateModelMixin创建一本新书,并保存到数据库
retrieve(self, request, pk=None)GET/books/{id}/RetrieveModelMixin获取单本书籍的详细信息
update(self, request, pk=None)PUT/books/{id}/UpdateModelMixin更新整条书籍记录(所有字段都要传)
partial_update(self, request, pk=None)PATCH/books/{id}/UpdateModelMixin局部更新书籍(只更新提交的字段)
destroy(self, request, pk=None)DELETE/books/{id}/DestroyModelMixin删除一本书籍
recent(self, request)GET/books/recent/自定义 @action获取最近出版的 5 本书

说明

  1. 默认方法 来自 DRF 的 ModelViewSet(继承了一组 mixin)。

  2. 自定义方法 使用 @action 装饰器,可以定义新的 API 路径。

    • detail=False → 不需要主键(例如 /books/recent/
    • detail=True → 需要主键(例如 /books/{id}/publish/

5. 常见扩展与自定义

5.1 权限控制

from rest_framework.permissions import IsAuthenticated

class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    permission_classes = [IsAuthenticated]

5.2 过滤与搜索

from rest_framework import filters

class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    filter_backends = [filters.SearchFilter, filters.OrderingFilter]
    search_fields = ['title', 'author']
    ordering_fields = ['published_date', 'price']

5.3 自定义方法(额外接口)

from rest_framework.decorators import action
from rest_framework.response import Response

class BookViewSet(viewsets.ModelViewSet):
    queryset = Book.objects.all()
    serializer_class = BookSerializer

    @action(detail=False, methods=['get'])
    def recent(self, request):
        books = self.queryset.order_by('-published_date')[:5]
        serializer = self.get_serializer(books, many=True)
        return Response(serializer.data)

现在 /books/recent/ 就是一个新接口。


6. 适用场景

✅ 适合:

  • 快速开发 标准化的 CRUD 接口
  • 数据表和 API 一一对应的场景
  • 中小型项目、原型开发

⚠️ 不太适合:

  • 大型系统中业务逻辑复杂、接口与模型关系不直接对应的场景
  • 接口过于定制化,不完全遵循 RESTful CRUD 的场景

在复杂项目中,可能需要继承 GenericViewSet + 部分 Mixins,而不是用 ModelViewSet 一把梭。


7. 最佳实践

  • 小项目:直接用 ModelViewSet + router,快速开发

  • 中大型项目:

    • ModelViewSet 用于简单、标准 CRUD
    • 自定义 GenericViewSet / APIView 用于复杂业务
    • views/ 目录下按业务模块拆分,而不是所有 ViewSet 放在一个文件里
    • 配合 序列化器分层(输入 / 输出不同 Serializer)提高可维护性

原文地址:https://blog.csdn.net/qq_44810930/article/details/151372610

免责声明:本站文章内容转载自网络资源,如侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!