Django REST Framework 教程:深入理解请求与响应处理
作为 Django REST Framework (DRF) 的核心组件,请求(Request)和响应(Response)对象构成了 Web API 开发的基础。本文将深入探讨这些关键概念,帮助开发者构建更强大、更灵活的 RESTful API。
一、DRF 的请求对象解析
DRF 对 Django 原生的 HttpRequest 进行了扩展,提供了更加强大的 Request
对象。这个增强版的请求对象特别适合处理各种类型的 API 请求。
核心特性对比
传统 Django 的 request.POST
有以下限制:
- 仅能处理表单数据
- 仅适用于 POST 方法
而 DRF 的 request.data
则提供了:
- 任意数据的处理能力(JSON、表单数据等)
- 支持 POST、PUT 和 PATCH 等多种 HTTP 方法
- 统一的数据访问接口
# 传统 Django 方式
def view(request):
if request.method == 'POST':
data = request.POST # 只能获取表单数据
# DRF 方式
@api_view(['POST'])
def view(request):
data = request.data # 可以获取各种格式的请求数据
二、DRF 的响应对象详解
DRF 的 Response
对象是一个智能的响应处理器,它能够根据客户端请求自动确定最合适的内容类型进行返回。
响应对象特点
- 内容协商:自动根据客户端 Accept 头决定返回格式(JSON、XML 等)
- 模板响应:继承自 Django 的 TemplateResponse
- 简化开发:开发者只需关注数据本身,无需处理格式转换
from rest_framework.response import Response
@api_view(['GET'])
def example_view(request):
data = {'message': 'Hello, World!'}
return Response(data) # DRF 会自动处理内容类型
三、HTTP 状态码的最佳实践
DRF 提供了可读性更强的状态码常量,替代难以记忆的数字代码:
from rest_framework import status
# 不推荐的方式
return Response(serializer.errors, status=400)
# 推荐的方式
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
常用状态码常量包括:
HTTP_200_OK
- 请求成功HTTP_201_CREATED
- 资源创建成功HTTP_400_BAD_REQUEST
- 客户端错误HTTP_404_NOT_FOUND
- 资源不存在HTTP_500_INTERNAL_SERVER_ERROR
- 服务器错误
四、API 视图包装器
DRF 提供了两种视图包装方式,简化 API 开发:
1. 函数视图装饰器 @api_view
from rest_framework.decorators import api_view
@api_view(['GET', 'POST'])
def snippet_list(request):
# 视图逻辑
2. 类视图基类 APIView
from rest_framework.views import APIView
class SnippetList(APIView):
def get(self, request):
# 处理 GET 请求
def post(self, request):
# 处理 POST 请求
这些包装器提供了以下功能:
- 自动将 Django 的 HttpRequest 转换为 DRF 的 Request
- 为 Response 添加上下文,实现内容协商
- 自动处理 405 Method Not Allowed 错误
- 捕获并处理输入数据解析错误
五、完整示例:代码片段 API
让我们看一个完整的代码片段 API 实现:
列表视图
@api_view(['GET', 'POST'])
def snippet_list(request):
"""
列出所有代码片段,或创建新片段
"""
if request.method == 'GET':
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = SnippetSerializer(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)
详情视图
@api_view(['GET', 'PUT', 'DELETE'])
def snippet_detail(request, pk):
"""
获取、更新或删除代码片段
"""
try:
snippet = Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = SnippetSerializer(snippet)
return Response(serializer.data)
elif request.method == 'PUT':
serializer = SnippetSerializer(snippet, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
snippet.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
六、支持多种响应格式
DRF 的一个强大特性是支持通过 URL 后缀指定响应格式:
1. 修改视图函数
def snippet_list(request, format=None):
# 视图逻辑
def snippet_detail(request, pk, format=None):
# 视图逻辑
2. 配置 URL
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views
urlpatterns = [
path('snippets/', views.snippet_list),
path('snippets/<int:pk>/', views.snippet_detail),
]
urlpatterns = format_suffix_patterns(urlpatterns)
现在 API 支持以下格式:
/snippets.json
- JSON 格式/snippets.api
- 可浏览的 API 格式
七、测试 API
可以使用命令行工具测试 API 的各种功能:
获取片段列表
http http://127.0.0.1:8000/snippets/
指定响应格式
http http://127.0.0.1:8000/snippets.json # JSON 格式
http http://127.0.0.1:8000/snippets.api # 可浏览 API
控制请求格式
# 表单形式提交
http --form POST http://127.0.0.1:8000/snippets/ code="print(123)"
# JSON 形式提交
http --json POST http://127.0.0.1:8000/snippets/ code="print(456)"
八、可浏览的 API 特性
DRF 的一个显著优势是自动提供 Web 可浏览的 API 界面:
- 当通过浏览器访问时,返回 HTML 格式的响应
- 极大提升了 API 的可用性和开发体验
- 降低了其他开发者使用 API 的门槛
只需在浏览器中访问 API 端点,就能获得交互式的文档和测试界面。
总结
通过本教程,我们深入了解了 Django REST Framework 中请求和响应的处理机制。这些核心概念为构建灵活、强大的 RESTful API 奠定了基础。下一阶段,我们将探索如何使用基于类的视图来进一步简化 API 开发。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考