Django REST Framework (DRF) 视图类详解
DRF 提供了丰富的视图类来构建 API,从基础到高级,满足不同复杂度的需求。以下是 DRF 的主要视图类及其使用场景:
1. 基础视图类
APIView
所有 DRF 视图的基类,相当于 Django 的 View 类的增强版。
from rest_framework.views import APIView
from rest_framework.response import Response
class ArticleAPIView(APIView):
def get(self, request):
articles = Article.objects.all()
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
def post(self, request):
serializer = ArticleSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=201)
return Response(serializer.errors, status=400)
特点:
-
提供了 Django View 的所有功能
-
增加了 DRF 的请求/响应处理
-
内置了认证、权限、限流等机制
2. 通用视图类 (Generic Views)
GenericAPIView
扩展了 APIView,增加了常见的列表和详情视图行为。
from rest_framework.generics import GenericAPIView
class ArticleList(GenericAPIView):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
def get(self, request):
queryset = self.get_queryset()
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
具体通用视图
DRF 提供了5个具体的通用视图类:
-
ListAPIView - 只读列表
from rest_framework.generics import ListAPIView class ArticleList(ListAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer
-
RetrieveAPIView - 只读单个实例
from rest_framework.generics import RetrieveAPIView class ArticleDetail(RetrieveAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer
-
CreateAPIView - 只创建
from rest_framework.generics import CreateAPIView class ArticleCreate(CreateAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer
-
UpdateAPIView - 只更新
from rest_framework.generics import UpdateAPIView class ArticleUpdate(UpdateAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer
-
DestroyAPIView - 只删除
from rest_framework.generics import DestroyAPIView class ArticleDelete(DestroyAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer
组合通用视图
-
ListCreateAPIView - 列表 + 创建
from rest_framework.generics import ListCreateAPIView class ArticleListCreate(ListCreateAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer
-
RetrieveUpdateAPIView - 详情 + 更新
from rest_framework.generics import RetrieveUpdateAPIView class ArticleRetrieveUpdate(RetrieveUpdateAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer
-
RetrieveDestroyAPIView - 详情 + 删除
from rest_framework.generics import RetrieveDestroyAPIView class ArticleRetrieveDestroy(RetrieveDestroyAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer
-
RetrieveUpdateDestroyAPIView - 详情 + 更新 + 删除
from rest_framework.generics import RetrieveUpdateDestroyAPIView class ArticleRUD(RetrieveUpdateDestroyAPIView): queryset = Article.objects.all() serializer_class = ArticleSerializer
3. 视图集 (ViewSets)
ViewSet
将多个视图逻辑组合到一个类中。
from rest_framework.viewsets import ViewSet
class ArticleViewSet(ViewSet):
def list(self, request):
queryset = Article.objects.all()
serializer = ArticleSerializer(queryset, many=True)
return Response(serializer.data)
def retrieve(self, request, pk=None):
article = get_object_or_404(Article, pk=pk)
serializer = ArticleSerializer(article)
return Response(serializer.data)
GenericViewSet
结合了 GenericAPIView 和 ViewSet 的行为。
from rest_framework.viewsets import GenericViewSet
class ArticleViewSet(GenericViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
def list(self, request):
queryset = self.get_queryset()
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
ModelViewSet
提供完整的 CRUD 操作。
from rest_framework.viewsets import ModelViewSet
class ArticleViewSet(ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
# 自动获得 list, create, retrieve, update, destroy 方法
ReadOnlyModelViewSet
只提供只读操作。
from rest_framework.viewsets import ReadOnlyModelViewSet
class ArticleViewSet(ReadOnlyModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
# 自动获得 list 和 retrieve 方法
4. 自定义动作
可以在 ViewSet 中添加自定义路由和方法:
from rest_framework.decorators import action
from rest_framework.response import Response
class ArticleViewSet(ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
@action(detail=True, methods=['post'])
def publish(self, request, pk=None):
article = self.get_object()
article.published = True
article.save()
return Response({'status': 'published'})
@action(detail=False)
def recent(self, request):
recent_articles = Article.objects.order_by('-created_at')[:5]
serializer = self.get_serializer(recent_articles, many=True)
return Response(serializer.data)
5. 其他特殊视图
mixins
可以组合使用的混合类:
-
ListModelMixin - 提供列表功能
-
CreateModelMixin - 提供创建功能
-
RetrieveModelMixin - 提供详情功能
-
UpdateModelMixin - 提供更新功能
-
DestroyModelMixin - 提供删除功能
from rest_framework import mixins
from rest_framework.viewsets import GenericViewSetclass ArticleViewSet(mixins.ListModelMixin,
mixins.CreateModelMixin,
GenericViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
视图选择指南
-
简单API:使用 APIView 或 GenericAPIView
-
标准CRUD:使用通用视图 (ListCreateAPIView 等) 或 ModelViewSet
-
只读API:使用 ReadOnlyModelViewSet
-
需要自定义行为:使用 ViewSet 或 GenericViewSet 配合 mixins
-
复杂逻辑:从 APIView 继承并自行实现
路由配置示例
# 对于 ViewSet
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'articles', ArticleViewSet)
urlpatterns = [
path('', include(router.urls)),
]
# 对于通用视图
urlpatterns = [
path('articles/', ArticleList.as_view()),
path('articles/<int:pk>/', ArticleDetail.as_view()),
]
DRF 的视图系统非常灵活,可以根据项目需求选择合适的视图类,从简单到复杂都能很好地支持。
应用示例
创建一个django项目
创建 Django 项目
django-admin startproject test_rest
cd test_rest
创建应用
python manage.py startapp myapp
下载
pip install djangorestframework
django项目注释掉一些不需要的,然后注册rest_framework
注释INSTALLED_APPS,MIDDLEWARE,TEMPLATES里自带的一些内容
#settings.py
"""
Django settings for test_rest project.
Generated by 'django-admin startproject' using Django 5.2.5.
For more information on this file, see
https://docs.djangoproject.com/en/5.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/5.2/ref/settings/
"""
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/5.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-!07)9y63bmcjs7__+me1a^sirkne20g1lz37bqrt&rt#%(5g1h'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
# 'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
# 'django.contrib.sessions',
# 'django.contrib.messages',
'django.contrib.staticfiles',
"rest_framework"
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
#'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
# 'django.contrib.auth.middleware.AuthenticationMiddleware',
# 'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
ROOT_URLCONF = 'test_rest.urls'
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.request',
# 'django.contrib.auth.context_processors.auth',
# 'django.contrib.messages.context_processors.messages',
],
},
},
]
WSGI_APPLICATION = 'test_rest.wsgi.application'
# Database
# https://docs.djangoproject.com/en/5.2/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
# Password validation
# https://docs.djangoproject.com/en/5.2/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
},
{
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
},
]
# Internationalization
# https://docs.djangoproject.com/en/5.2/topics/i18n/
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'UTC'
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/5.2/howto/static-files/
STATIC_URL = 'static/'
# Default primary key field type
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
Django REST Framework (DRF) 中的 FBV 与 CBV
FBV(Function-Based Views,函数基础视图)和 CBV(Class-Based Views,类基础视图)是 Django 和 Django REST Framework (DRF) 中实现视图逻辑的两种主要方式。
test_rest/urls.py
"""
URL configuration for test_rest project.
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/5.2/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.urls import path,include
from myapp import views
urlpatterns = [
path('auth/',views.auth), #FBV
path('myview/',views.MyView.as_view()),#CBV
path('info/',views.MyView.as_view()),#CBV
]
/myapp/views.py
from django.http import JsonResponse
from django.views import View
from rest_framework.views import APIView
from rest_framework.response import Response
def auth(request):
if request.method == "GET":
return JsonResponse({"status":True,'message':'success',"method":request.method})
elif request.method == "POST":
return JsonResponse({"status":True,'message':'success',"method":request.method})
return JsonResponse({"status":False,"method":request.method})
class MyView(View):
def get(self,request):
return JsonResponse({"status":True,'message':'success',"method":request.method})
def post(self,request):
return JsonResponse({"status":True,'message':'success',"method":request.method})
def put(self,request):
return JsonResponse({"status":True,'message':'success',"method":request.method})
def delete(self,request):
return JsonResponse({"status":True,'message':'success',"method":request.method})
class InfoView(APIView):
def get(self,request):
return Response({"status":True,'message':'success',"method":request.method})
Django REST Framework (DRF) 视图类详解
DRF 提供了丰富的视图类来构建 API,从基础到高级,满足不同复杂度的需求。以下是 DRF 的主要视图类及其使用场景:
开始前咱们先创建一个数据库,模型类,然后迁移数据
一、MySQL 数据库配置
1. 安装 MySQL 驱动
pip install mysqlclient # 推荐
# 或
pip install pymysql
2. 创建 MySQL 数据库
CREATE DATABASE backstage CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
3. 配置 Django 的 settings.py
# settings.py
DATABASES = {
'default': { # 默认数据库配置(Django 支持多数据库配置)
'ENGINE': 'django.db.backends.mysql', # 指定使用 MySQL 后端
'NAME': 'backstage', # 数据库名(需提前创建)
'USER': 'your_username', # MySQL 用户名
'PASSWORD': 'your_password', # MySQL 密码
'HOST': 'localhost', # 数据库服务器地址(默认本地)
'PORT': '3306', # MySQL 默认端口
'OPTIONS': { # 额外选项(关键配置)
'charset': 'utf8mb4', # 字符集设置为 utf8mb4
'init_command': "SET sql_mode='STRICT_TRANS_TABLES'", # 初始化 SQL 命令
}
}
}
二、创建商品模型
定义模型(myapp/models.py)
from django.db import models
from django.core.validators import MinValueValidator
class SpecificationCategory(models.Model):
"""规格类目表"""
id = models.AutoField(primary_key=True, verbose_name="商品ID")
name = models.CharField(max_length=50, verbose_name="规格类目名称")
cid = models.CharField(max_length=50, verbose_name="类目编号")
class Meta:
db_table = 'spec_category'
verbose_name = '商品规格类目'
verbose_name_plural = verbose_name
def __str__(self):
return self.name
class Product(models.Model):
"""商品表"""
id = models.AutoField(primary_key=True, verbose_name="商品ID")
price = models.DecimalField(
max_digits=10,
decimal_places=2,
validators=[MinValueValidator(0)],
verbose_name="商品价格"
)
stock = models.PositiveIntegerField(default=0, verbose_name="商品库存")
# 一对多关联规格类目
spec_category = models.ForeignKey(
SpecificationCategory,
on_delete=models.PROTECT,
related_name='products', # 注意改为复数形式
verbose_name="规格类目"
)
image = models.CharField(
max_length=500,
blank=True,
null=True,
verbose_name="商品主图URL"
)
selling_points = models.CharField(
max_length=200,
blank=True,
verbose_name="商品卖点"
)
description = models.TextField(verbose_name="商品详情描述")
# 自动记录时间
created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")
class Meta:
db_table = 'product'
verbose_name = '商品信息'
verbose_name_plural = verbose_name
ordering = ['-created_at']
def __str__(self):
return f"商品{self.id}(库存:{self.stock})"
三、数据库迁移
注意要在settings.py里注册app哦

1. 生成迁移文件
python manage.py makemigrations myapp
2. 查看生成的SQL(可选)
python manage.py sqlmigrate myapp 0001
3. 执行迁移
python manage.py migrate
示例
1. 首先创建序列化器
在 serializers.py
中:
from rest_framework import serializers
from .models import Product, SpecificationCategory
class SpecificationCategorySerializer(serializers.ModelSerializer):
class Meta:
model = SpecificationCategory
fields = ['id', 'name', 'cid']
class ProductSerializer(serializers.ModelSerializer):
# 保留只读的嵌套表示
spec_category = SpecificationCategorySerializer(read_only=True)
# 改为只接受spec_category的ID
spec_category_id = serializers.PrimaryKeyRelatedField(
queryset=SpecificationCategory.objects.all(),
source='spec_category',
write_only=True
)
class Meta:
model = Product
fields = [
'id', 'price', 'stock', 'spec_category',
'image', 'selling_points', 'description',
'created_at', 'updated_at'
]
read_only_fields = ['created_at', 'updated_at']
APIView 使用示例
2. 创建 APIView 视图
在 views.py
中:
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Product
from .serializers import ProductSerializer
from django.shortcuts import get_object_or_404
class ProductAPIView(APIView):
"""
商品API视图,支持列表获取和创建
"""
def get(self, request, format=None):
"""
获取所有商品列表
"""
products = Product.objects.all()
serializer = ProductSerializer(products, many=True)
return Response(serializer.data)
def post(self, request, format=None):
"""
创建新商品
"""
serializer = ProductSerializer(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)
class ProductDetailAPIView(APIView):
"""
商品详情API视图,支持检索、更新和删除单个商品
"""
def get_object(self, pk):
return get_object_or_404(Product, pk=pk)
def get(self, request, pk, format=None):
"""
获取单个商品详情
"""
product = self.get_object(pk)
serializer = ProductSerializer(product)
return Response(serializer.data)
def put(self, request, pk, format=None):
"""
更新整个商品信息
"""
product = self.get_object(pk)
serializer = ProductSerializer(product, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def patch(self, request, pk, format=None):
"""
部分更新商品信息
"""
product = self.get_object(pk)
serializer = ProductSerializer(product, data=request.data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
"""
删除商品
"""
product = self.get_object(pk)
product.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
3. 配置 URL 路由
在 urls.py
中:
from django.urls import path
from myapp.views import ProductAPIView,ProductDetailAPIView
urlpatterns = [
path('products/', ProductAPIView.as_view(), name='product-list'),
path('products/<int:pk>/', ProductDetailAPIView.as_view(), name='product-detail'),
]
访问:


ViewSets的ModelViewSet示例
2. 创建 APIView 视图
在 views.py
中:
from .models import Product,SpecificationCategory
from .serializers import ProductSerializer,SpecificationCategorySerializer
from rest_framework import viewsets
class SpecificationCategoryViewSet(viewsets.ModelViewSet):
queryset = SpecificationCategory.objects.all()
serializer_class = SpecificationCategorySerializer
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
3. 配置 URL 路由
在 urls.py
中:
from django.urls import path, include
from myapp.views import *
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register('spec-categories', SpecificationCategoryViewSet)
router.register('products_view', ProductViewSet)
urlpatterns = [
path('api/', include(router.urls)), # 注意这里包含了路由
]
访问:


