Django REST框架:ModelViewSet全面解析

发布于:2025-09-10 ⋅ 阅读:(18) ⋅ 点赞:(0)

介绍 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)提高可维护性

网站公告

今日签到

点亮在社区的每一天
去签到