DRF 类视图整理
本文整理 Django REST framework 常见类视图,按层次和用途分类,并给出最小可运行的 view 与 url 示例。本文默认面向前后端分离场景,前端通过 HTTP 调用这些接口。
快速对照表
| 类名 | 层次 | 主要用途 | 常用程度 |
|---|---|---|---|
views.APIView | 基础 API 视图 | 手写请求处理 | 很常用 |
generics.GenericAPIView | 带 queryset/serializer 的基础视图 | 自定义通用 API | 常用 |
mixins.CreateModelMixin | 行为 mixin | 创建 | 常用 |
mixins.ListModelMixin | 行为 mixin | 列表 | 常用 |
mixins.RetrieveModelMixin | 行为 mixin | 详情 | 常用 |
mixins.UpdateModelMixin | 行为 mixin | 更新 | 常用 |
mixins.DestroyModelMixin | 行为 mixin | 删除 | 常用 |
generics.CreateAPIView | 通用视图 | 创建 | 很常用 |
generics.ListAPIView | 通用视图 | 列表 | 很常用 |
generics.RetrieveAPIView | 通用视图 | 详情 | 很常用 |
generics.UpdateAPIView | 通用视图 | 更新 | 常用 |
generics.DestroyAPIView | 通用视图 | 删除 | 常用 |
generics.ListCreateAPIView | 通用视图 | 列表 + 创建 | 很常用 |
generics.RetrieveUpdateAPIView | 通用视图 | 详情 + 更新 | 常用 |
generics.RetrieveDestroyAPIView | 通用视图 | 详情 + 删除 | 常用 |
generics.RetrieveUpdateDestroyAPIView | 通用视图 | 详情 + 更新 + 删除 | 很常用 |
viewsets.ViewSet | 资源视图集 | 自定义一组动作 | 常用 |
viewsets.GenericViewSet | 资源视图集 | mixin 组合 | 常用 |
viewsets.ModelViewSet | 资源视图集 | 完整 CRUD | 很常用 |
viewsets.ReadOnlyModelViewSet | 资源视图集 | 只读接口 | 很常用 |
说明
- 在前后端分离项目里,最常用的一般是:
APIView、ListCreateAPIView、RetrieveUpdateDestroyAPIView、ModelViewSet。 - 如果你想完全掌控接口细节,用
APIView。 - 如果你想减少样板代码,用
generics。 - 如果你想把同一资源的多个动作统一管理,优先考虑
ViewSet/ModelViewSet。 - 新人学习顺序建议:
APIView -> GenericAPIView -> ListCreateAPIView -> RetrieveUpdateDestroyAPIView -> ModelViewSet。
1. DRF 类视图整体层次
DRF 类视图可以粗略理解成下面这条线:
APIView -> GenericAPIView -> Mixins / Generics -> ViewSet / ModelViewSet
APIView:最基础的 API 类视图GenericAPIView:增加queryset、serializer_class等通用能力Mixins:把列表、新增、更新、删除等行为拆成可复用模块Generics:把GenericAPIView + Mixins组合成常用接口ViewSet:把一组 CRUD 接口组织到一个类里
以下示例默认使用模型和序列化器:
# models.py
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.CharField(max_length=100)
published_date = models.DateField()
def __str__(self):
return self.title
# serializers.py
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = ['id', 'title', 'author', 'published_date']
2. APIView
作用:最基础的 DRF 类视图,需要自己手动处理 get()、post() 等方法。
# views.py
from rest_framework import status
from rest_framework.response import Response
from rest_framework import views
from .models import Book
from .serializers import BookSerializer
class BookManualCreateView(views.APIView):
def post(self, request, *args, **kwargs):
serializer = BookSerializer(data=request.data)
if serializer.is_valid():
book = serializer.save()
return Response(BookSerializer(book).data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# urls.py
from django.urls import path
from .views import BookManualCreateView
urlpatterns = [
path('books/manual-create/', BookManualCreateView.as_view(), name='book-manual-create'),
]
3. GenericAPIView
作用:在 APIView 基础上增加通用属性和方法,如:
querysetserializer_classget_queryset()get_serializer()get_object()
单独用它时,通常还需要自己写具体的 HTTP 方法。
# views.py
from rest_framework import status
from rest_framework import generics
from rest_framework.response import Response
from .models import Book
from .serializers import BookSerializer
class BookGenericCreateView(generics.GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
# urls.py
from django.urls import path
from .views import BookGenericCreateView
urlpatterns = [
path('books/generic-create/', BookGenericCreateView.as_view(), name='book-generic-create'),
]
4. Mixins 系列
Mixins 本身通常不会直接单独拿来当视图用,而是搭配 GenericAPIView 或 ViewSet 使用。
4.1 CreateModelMixin
作用:提供创建对象能力,对应 create()。
from rest_framework import generics, mixins
from .models import Book
from .serializers import BookSerializer
class BookCreateMixinView(mixins.CreateModelMixin, generics.GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
from django.urls import path
from .views import BookCreateMixinView
urlpatterns = [
path('books/create-mixin/', BookCreateMixinView.as_view(), name='book-create-mixin'),
]
4.2 ListModelMixin
作用:提供列表查询能力,对应 list()。
from rest_framework import generics, mixins
from .models import Book
from .serializers import BookSerializer
class BookListMixinView(mixins.ListModelMixin, generics.GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
from django.urls import path
from .views import BookListMixinView
urlpatterns = [
path('books/list-mixin/', BookListMixinView.as_view(), name='book-list-mixin'),
]
4.3 RetrieveModelMixin
作用:提供详情查询能力,对应 retrieve()。
from rest_framework import generics, mixins
from .models import Book
from .serializers import BookSerializer
class BookRetrieveMixinView(mixins.RetrieveModelMixin, generics.GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
from django.urls import path
from .views import BookRetrieveMixinView
urlpatterns = [
path('books/<int:pk>/retrieve-mixin/', BookRetrieveMixinView.as_view(), name='book-retrieve-mixin'),
]
4.4 UpdateModelMixin
作用:提供更新能力,对应 update() 和 partial_update()。
from rest_framework import generics, mixins
from .models import Book
from .serializers import BookSerializer
class BookUpdateMixinView(mixins.UpdateModelMixin, generics.GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def patch(self, request, *args, **kwargs):
return self.partial_update(request, *args, **kwargs)
from django.urls import path
from .views import BookUpdateMixinView
urlpatterns = [
path('books/<int:pk>/update-mixin/', BookUpdateMixinView.as_view(), name='book-update-mixin'),
]
4.5 DestroyModelMixin
作用:提供删除能力,对应 destroy()。
from rest_framework import generics, mixins
from .models import Book
from .serializers import BookSerializer
class BookDestroyMixinView(mixins.DestroyModelMixin, generics.GenericAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
from django.urls import path
from .views import BookDestroyMixinView
urlpatterns = [
path('books/<int:pk>/destroy-mixin/', BookDestroyMixinView.as_view(), name='book-destroy-mixin'),
]
5. GenericAPIView + Mixins 组合视图
这些是 DRF 最常见的一组现成通用 API 视图。
5.1 CreateAPIView
作用:只负责创建。
from rest_framework import generics
from .models import Book
from .serializers import BookSerializer
class BookCreateAPIView(generics.CreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
from django.urls import path
from .views import BookCreateAPIView
urlpatterns = [
path('books/create/', BookCreateAPIView.as_view(), name='book-create'),
]
5.2 ListAPIView
作用:只负责列表。
from rest_framework import generics
from .models import Book
from .serializers import BookSerializer
class BookListAPIView(generics.ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
from django.urls import path
from .views import BookListAPIView
urlpatterns = [
path('books/list/', BookListAPIView.as_view(), name='book-list'),
]
5.3 RetrieveAPIView
作用:只负责单条详情。
from rest_framework import generics
from .models import Book
from .serializers import BookSerializer
class BookRetrieveAPIView(generics.RetrieveAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
from django.urls import path
from .views import BookRetrieveAPIView
urlpatterns = [
path('books/<int:pk>/', BookRetrieveAPIView.as_view(), name='book-detail'),
]
5.4 UpdateAPIView
作用:只负责更新。
from rest_framework import generics
from .models import Book
from .serializers import BookSerializer
class BookUpdateAPIView(generics.UpdateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
from django.urls import path
from .views import BookUpdateAPIView
urlpatterns = [
path('books/<int:pk>/update/', BookUpdateAPIView.as_view(), name='book-update'),
]
5.5 DestroyAPIView
作用:只负责删除。
from rest_framework import generics
from .models import Book
from .serializers import BookSerializer
class BookDestroyAPIView(generics.DestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
from django.urls import path
from .views import BookDestroyAPIView
urlpatterns = [
path('books/<int:pk>/delete/', BookDestroyAPIView.as_view(), name='book-delete'),
]
5.6 ListCreateAPIView
作用:列表 + 创建。
from rest_framework import generics
from .models import Book
from .serializers import BookSerializer
class BookListCreateAPIView(generics.ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
from django.urls import path
from .views import BookListCreateAPIView
urlpatterns = [
path('books/', BookListCreateAPIView.as_view(), name='book-list-create'),
]
5.7 RetrieveUpdateAPIView
作用:详情 + 更新。
from rest_framework import generics
from .models import Book
from .serializers import BookSerializer
class BookRetrieveUpdateAPIView(generics.RetrieveUpdateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
from django.urls import path
from .views import BookRetrieveUpdateAPIView
urlpatterns = [
path('books/<int:pk>/detail-update/', BookRetrieveUpdateAPIView.as_view(), name='book-detail-update'),
]
5.8 RetrieveDestroyAPIView
作用:详情 + 删除。
from rest_framework import generics
from .models import Book
from .serializers import BookSerializer
class BookRetrieveDestroyAPIView(generics.RetrieveDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
from django.urls import path
from .views import BookRetrieveDestroyAPIView
urlpatterns = [
path('books/<int:pk>/detail-delete/', BookRetrieveDestroyAPIView.as_view(), name='book-detail-delete'),
]
5.9 RetrieveUpdateDestroyAPIView
作用:详情 + 更新 + 删除。
from rest_framework import generics
from .models import Book
from .serializers import BookSerializer
class BookRetrieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
from django.urls import path
from .views import BookRetrieveUpdateDestroyAPIView
urlpatterns = [
path('books/<int:pk>/rud/', BookRetrieveUpdateDestroyAPIView.as_view(), name='book-rud'),
]
6. ViewSet 系列
ViewSet 适合把一组资源操作收拢到一个类里,常和路由器一起使用。
6.1 ViewSet
作用:最基础的 ViewSet,需要自己定义动作方法。
from rest_framework import viewsets
from rest_framework.response import Response
class BookViewSet(viewsets.ViewSet):
def list(self, request):
return Response({'message': 'list books'})
def retrieve(self, request, pk=None):
return Response({'message': f'detail of {pk}'})
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from .views import BookViewSet
router = DefaultRouter()
router.register('books-viewset', BookViewSet, basename='books-viewset')
urlpatterns = [
path('', include(router.urls)),
]
6.2 GenericViewSet
作用:结合 GenericAPIView 能力的 ViewSet,常和 mixins 搭配。
from rest_framework import mixins, viewsets
from .models import Book
from .serializers import BookSerializer
class BookGenericViewSet(mixins.ListModelMixin, mixins.CreateModelMixin, viewsets.GenericViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from .views import BookGenericViewSet
router = DefaultRouter()
router.register('books-generic-viewset', BookGenericViewSet, basename='books-generic-viewset')
urlpatterns = [
path('', include(router.urls)),
]
6.3 ModelViewSet
作用:最常用的 ViewSet,默认提供完整 CRUD。
from rest_framework import viewsets
from .models import Book
from .serializers import BookSerializer
class BookModelViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from .views import BookModelViewSet
router = DefaultRouter()
router.register('books-model-viewset', BookModelViewSet, basename='books-model-viewset')
urlpatterns = [
path('', include(router.urls)),
]
6.4 ReadOnlyModelViewSet
作用:只提供只读接口,通常是列表 + 详情。
from rest_framework import viewsets
from .models import Book
from .serializers import BookSerializer
class BookReadOnlyModelViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from .views import BookReadOnlyModelViewSet
router = DefaultRouter()
router.register('books-readonly', BookReadOnlyModelViewSet, basename='books-readonly')
urlpatterns = [
path('', include(router.urls)),
]
6.5 自定义路由@action
作用:在 ViewSet / ModelViewSet 现有 CRUD 之外,额外补充自定义接口。
常见有 3 种情况:
detail=True,不写url_path,默认使用方法名作为路径。detail=True,自定义url_path,面向单个对象。detail=False,自定义url_path,面向整个集合。
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from .models import Book
from .serializers import BookSerializer
class BookActionViewSet(viewsets.ModelViewSet):
queryset = Book.objects.all()
serializer_class = BookSerializer
@action(detail=True, methods=['post'])
def publish(self, request, pk=None):
book = self.get_object()
return Response({'message': f'publish book {book.pk}'}, status=status.HTTP_200_OK)
@action(detail=True, methods=['post'], url_path='publish-now')
def publish_now(self, request, pk=None):
book = self.get_object()
return Response({'message': f'publish now {book.pk}'}, status=status.HTTP_200_OK)
@action(detail=False, methods=['get'], url_path='recent')
def recent_books(self, request):
return Response({'message': 'recent books'}, status=status.HTTP_200_OK)
from django.urls import include, path
from rest_framework.routers import DefaultRouter
from .views import BookActionViewSet
router = DefaultRouter()
router.register('books-actions', BookActionViewSet, basename='books-actions')
urlpatterns = [
path('', include(router.urls)),
]
对应路由通常会是:
POST /books-actions/{pk}/publish/POST /books-actions/{pk}/publish-now/GET /books-actions/recent/
补充说明:
detail=True表示这是“单对象路由”,URL 里会带主键。detail=False表示这是“集合路由”,URL 里不带主键。url_path用来控制 URL 路径片段;如果不写,默认使用方法名。- 如果还需要控制反向解析名字,可以继续传
url_name='xxx'。
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/SDKL_YI/article/details/162232102



