从入门到"精通"Django REST Framework-(四)
一、什么是 APIView?
APIView 是 Django REST Framework (DRF) 中提供的基础视图类,继承自 Django 的 View 类,但针对 RESTful API 进行了扩展。它支持以下功能:
- 请求解析:自动解析请求体中的数据(如 JSON、表单数据)。
- 响应封装:提供
Response对象,支持内容协商(自动根据客户端需求返回 JSON 等格式)。 - 认证与权限:内置认证(如 Token、JWT)和权限控制(如用户权限、访问频率限制)。
- 异常处理:统一捕获 API 异常,返回结构化的错误响应。
二、为什么要使用 APIView?
相比 Django 原生的 View,APIView 更适合构建 RESTful API:
- 标准化请求/响应:自动解析请求数据并封装响应,无需手动处理
request.POST或JsonResponse。 - 内置功能丰富:直接集成认证、权限、限流等常用功能。
- 代码更简洁:通过重写
get(),post()等方法实现不同 HTTP 方法逻辑,符合 REST 规范。
三、基础用法
1. 创建视图类
列表页
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
class UserListView(APIView):
def get(self, request):
users = User.objects.all()
serializer = UserSerializer(users, many=True)
return Response(serializer.data)
详情页
class UserDetailView(APIView):
def get(self, request, user_id):
user = User.objects.get(id=user_id)
serializer = UserSerializer(user)
return Response(serializer.data)
def post(self, request):
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=201)
return Response(serializer.errors, status=400)
2. 配置 URL 路由
# urls.py
from django.urls import path
from .views import UserListView
urlpatterns = [
path('users/', UserListView.as_view(), name='user-list'),
path('users/<int:pk>/', UserDetailView.as_view(), name='user-detail'),
]
四、核心详解
请求数据访问
request.data:获取解析后的请求体数据(支持 JSON、表单等)。request.query_params:获取 URL 查询参数(等价于 Django 的request.GET)。request.method: 获取 HTTP 请求方法(如 GET、POST、PUT、DELETE 等)。request.GET: 获取 URL 查询参数(等价于 Django 的request.GET)。request.content_type: 获取请求的内容类型(Content-Type)。request.POST: 获取请求体中的表单数据(当Content-Type为application/x-www-form-urlencoded或multipart/form-data时)。
响应返回
return Response(
data={'message': 'Success'}, # 响应数据
status=201, # 状态码
headers={'X-Custom': 'value'} # 自定义响应头
)
主要属性
1.renderer_classes - 用于控制响应的渲染方式
- 默认值: settings.DEFAULT_RENDERER_CLASSES
- 例如: renderer_classes = [JSONRenderer, TemplateHTMLRenderer]
2.parser_classes - 用于解析请求内容
- 默认值: settings.DEFAULT_PARSER_CLASSES
- 例如: parser_classes = [JSONParser, FormParser, MultiPartParser]
3.authentication_classes - 用于认证
- 默认值: settings.DEFAULT_AUTHENTICATION_CLASSES
- 例如: authentication_classes = [TokenAuthentication, SessionAuthentication]
4.permission_classes - 用于权限控制
- 默认值: settings.DEFAULT_PERMISSION_CLASSES
- 例如: permission_classes = [IsAuthenticated, IsAdminUser]
5.throttle_classes - 用于限流控制
- 默认值: settings.DEFAULT_THROTTLE_CLASSES
- 例如: throttle_classes = [UserRateThrottle, AnonRateThrottle]
6.content_negotiation_class - 内容协商类
- 默认值: settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
- 例如: content_negotiation_class = DefaultContentNegotiation
7.metadata_class - 元数据类
- 默认值: settings.DEFAULT_METADATA_CLASS
- 例如: metadata_class = SimpleMetadata
8.versioning_class - API 版本控制类
- 默认值: settings.DEFAULT_VERSIONING_CLASS
- 例如: versioning_class = URLPathVersioning
9.schema - API 模式类
- 默认值: None (自动生成)
- 例如: schema = AutoSchema()
10.throttle_scope - 限流范围
- 默认值: None
- 例如: throttle_scope = 'user'
pagination_class - 分页类
注意!:这实际上是 GenericAPIView 的属性,不是基础 APIView 的属性
重要方法
APIView 还有一些可以重写的重要方法:
- initial(self, request, *args, **kwargs) - 在处理请求前的初始化
- handle_exception(self, exc) - 异常处理
- get_permissions(self) - 获取权限实例
- get_authenticators(self) - 获取认证器实例
- get_throttles(self) - 获取限流器实例
- get_content_negotiator(self) - 获取内容协商器实例
- get_exception_handler(self) - 获取异常处理器
这些属性和方法使 APIView 成为一个非常灵活和可配置的基础视图类,可以根据需要进行定制。
属性和方法的代码示例
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authentication, permissions, throttling, parsers, renderers
from rest_framework.schemas import AutoSchema
class ExampleAPIView(APIView):
# 渲染器 - 控制响应如何被渲染
renderer_classes = [renderers.JSONRenderer, renderers.BrowsableAPIRenderer]
# 解析器 - 控制如何解析请求数据
parser_classes = [parsers.JSONParser, parsers.FormParser, parsers.MultiPartParser]
# 认证 - 确定请求的用户身份
authentication_classes = [authentication.TokenAuthentication, authentication.SessionAuthentication]
# 权限 - 控制用户是否有权限执行操作
permission_classes = [permissions.IsAuthenticated]
# 限流 - 控制请求频率
throttle_classes = [throttling.UserRateThrottle, throttling.AnonRateThrottle]
# API 模式
schema = AutoSchema()
# 限流范围
throttle_scope = 'example_api'
def get(self, request, format=None):
"""
获取示例数据
"""
data = {'message': '这是一个示例响应'}
return Response(data)
def post(self, request, format=None):
"""
创建示例数据
"""
data = request.data
# 处理数据...
return Response({'received': data})
# 重写初始化方法
def initial(self, request, *args, **kwargs):
"""
在处理请求前执行初始化操作
"""
# 调用父类的 initial 方法
super().initial(request, *args, **kwargs)
# 自定义初始化逻辑
print(f"处理来自 {request.user} 的请求")
# 自定义异常处理
def handle_exception(self, exc):
"""
自定义异常处理
"""
if isinstance(exc, CustomException):
# 处理自定义异常
return Response({'error': str(exc)}, status=400)
# 其他异常交给父类处理
return super().handle_exception(exc)
自定义权限控制示例
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import permissions
# 自定义权限类
class IsOwnerOrReadOnly(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
# 读取权限允许任何请求
if request.method in permissions.SAFE_METHODS:
return True
# 写入权限只允许对象的所有者
return obj.owner == request.user
class UserProfileView(APIView):
permission_classes = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
def get(self, request, user_id):
# 获取用户资料
return Response({"user_id": user_id, "data": "用户资料"})
def put(self, request, user_id):
# 更新用户资料
return Response({"message": "资料已更新"})
# 重写获取权限方法
def get_permissions(self):
"""
根据请求方法动态设置权限
"""
if self.request.method == 'DELETE':
return [permissions.IsAdminUser()]
return [permission() for permission in self.permission_classes]
自定义认证和限流
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authentication, throttling
# 自定义限流类
class BurstRateThrottle(throttling.UserRateThrottle):
rate = '10/minute' # 每分钟10次请求
class SustainedRateThrottle(throttling.UserRateThrottle):
rate = '100/day' # 每天100次请求
class ApiEndpoint(APIView):
authentication_classes = [authentication.TokenAuthentication]
throttle_classes = [BurstRateThrottle, SustainedRateThrottle]
def get(self, request):
return Response({"message": "API响应"})
# 重写获取限流器方法
def get_throttles(self):
"""
根据用户类型动态设置限流
"""
if request.user.is_staff:
# 管理员用户不受限流限制
return []
return [throttle() for throttle in self.throttle_classes]
内容协商和版本控制
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.negotiation import DefaultContentNegotiation
from rest_framework.versioning import URLPathVersioning
class VersionedAPI(APIView):
content_negotiation_class = DefaultContentNegotiation
versioning_class = URLPathVersioning
def get(self, request, version):
if version == 'v1':
return Response({"version": "1.0", "data": "旧版API数据"})
return Response({"version": "2.0", "data": "新版API数据"})
元数据和模式
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.metadata import SimpleMetadata
from rest_framework.schemas import AutoSchema
class DocumentedAPI(APIView):
metadata_class = SimpleMetadata
schema = AutoSchema(
operation_id_base='example',
component_name='Example',
tags=['example-api']
)
def get(self, request):
"""
获取示例数据。
此端点返回一个示例数据对象。
"""
return Response({"example": "data"})
def post(self, request):
"""
创建新的示例数据。
提交数据将被处理并存储。
"""
return Response({"status": "created"})
异常处理
DRF 自动捕获 APIException 异常,返回标准错误响应。
可自定义异常处理逻辑:
def custom_exception_handler(exc, context):
response = exception_handler(exc, context)
if response:
response.data = {
'error': {
'code': response.status_code,
'message': response.data.get('detail', 'Error occurred')
}
}
return response
在 settings.py 中配置:
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'myapp.handlers.custom_exception_handler'
}
五、其他技巧
自定义响应格式
class CustomResponse(Response):
def __init__(self, data, **kwargs):
data = {'code': 0, 'msg': 'success', 'data': data}
super().__init__(data, **kwargs)
return CustomResponse(serializer.data)
文件上传
class FileUploadView(APIView):
parser_classes = [MultiPartParser] # 允许 multipart/form-data
def post(self, request):
file = request.FILES['file']
# 处理文件...
创建通用基类-复用
class BaseAPIView(APIView):
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
class UserView(BaseAPIView):
def get(self, request):
# 复用基类的认证和权限
每天进步一点点

浙公网安备 33010602011771号