首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >从入门到"精通"Django REST Framework-(四)

从入门到"精通"Django REST Framework-(四)

原创
作者头像
rxg456
发布2025-02-27 21:48:13
发布2025-02-27 21:48:13
3610
举报

一、什么是 APIView?

APIView 是 Django REST Framework (DRF) 中提供的基础视图类,继承自 Django 的 View 类,但针对 RESTful API 进行了扩展。它支持以下功能:

  • 请求解析:自动解析请求体中的数据(如 JSON、表单数据)。
  • 响应封装:提供 Response 对象,支持内容协商(自动根据客户端需求返回 JSON 等格式)。
  • 认证与权限:内置认证(如 Token、JWT)和权限控制(如用户权限、访问频率限制)。
  • 异常处理:统一捕获 API 异常,返回结构化的错误响应。

二、为什么要使用 APIView?

相比 Django 原生的 ViewAPIView 更适合构建 RESTful API:

  1. 标准化请求/响应:自动解析请求数据并封装响应,无需手动处理 request.POSTJsonResponse
  2. 内置功能丰富:直接集成认证、权限、限流等常用功能。
  3. 代码更简洁:通过重写 get(), post() 等方法实现不同 HTTP 方法逻辑,符合 REST 规范。

三、基础用法

1. 创建视图类

列表页
代码语言:javascript
复制
# 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)
详情页
代码语言:javascript
复制
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 路由

代码语言:javascript
复制
# 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-Typeapplication/x-www-form-urlencodedmultipart/form-data 时)。

响应返回

代码语言:javascript
复制
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 成为一个非常灵活和可配置的基础视图类,可以根据需要进行定制。

属性和方法的代码示例

代码语言:javascript
复制
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)
自定义权限控制示例
代码语言:javascript
复制
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]
自定义认证和限流
代码语言:javascript
复制
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]
内容协商和版本控制
代码语言:javascript
复制
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数据"})
元数据和模式
代码语言:javascript
复制
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 异常,返回标准错误响应。 可自定义异常处理逻辑:

代码语言:javascript
复制
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 中配置:

代码语言:javascript
复制
REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'myapp.handlers.custom_exception_handler'
}

五、其他技巧

自定义响应格式

代码语言:javascript
复制
class CustomResponse(Response):
    def __init__(self, data, **kwargs):
        data = {'code': 0, 'msg': 'success', 'data': data}
        super().__init__(data, **kwargs)

return CustomResponse(serializer.data)

文件上传

代码语言:javascript
复制
class FileUploadView(APIView):
    parser_classes = [MultiPartParser]  # 允许 multipart/form-data

    def post(self, request):
        file = request.FILES['file']
        # 处理文件...

创建通用基类-复用

代码语言:javascript
复制
class BaseAPIView(APIView):
    authentication_classes = [TokenAuthentication]
    permission_classes = [IsAuthenticated]

class UserView(BaseAPIView):
    def get(self, request):
        # 复用基类的认证和权限

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、什么是 APIView?
  • 二、为什么要使用 APIView?
  • 三、基础用法
    • 1. 创建视图类
      • 列表页
      • 详情页
    • 2. 配置 URL 路由
  • 四、核心详解
    • 请求数据访问
    • 响应返回
    • 主要属性
      • 1.renderer_classes - 用于控制响应的渲染方式
      • 2.parser_classes - 用于解析请求内容
      • 3.authentication_classes - 用于认证
      • 4.permission_classes - 用于权限控制
      • 5.throttle_classes - 用于限流控制
      • 6.content_negotiation_class - 内容协商类
      • 7.metadata_class - 元数据类
      • 8.versioning_class - API 版本控制类
      • 9.schema - API 模式类
      • 10.throttle_scope - 限流范围
      • pagination_class - 分页类
    • 重要方法
    • 属性和方法的代码示例
      • 自定义权限控制示例
      • 自定义认证和限流
      • 内容协商和版本控制
      • 元数据和模式
    • 异常处理
  • 五、其他技巧
    • 自定义响应格式
    • 文件上传
    • 创建通用基类-复用
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档