请求对象
REST framework引入了一个扩展常规HttpRequest的Request对象,并提供了灵活的请求解析。
Request对象的核心功能是request.data属性,它去request.POST类似,但对于使用Web API更加有用。
request.POST # 用于处理表单数据,仅限于POST方法
request.data # 处理任意数据,适用于POST, PUT和PATCH方法
响应请求
REST framework还引入了一个Response对象,该对象是一种获取为渲染内容的TemplateResponse
类型并使用内容协商来确定正确内容类型返回给客户端。
return Response(data) # 渲染成客户端请求的内容类型
状态码
在视图代码中使用数字HTTP状态码并总是有利于代码的阅读,如果写错状态码,很容易被忽略。REST framework为每个状态码提供更明确的标识符,如status中的HTTP_400_BAD_REQUEST
。
包装API视图
REST framework提供了两种编写API视图的封装:
- 基于函数视图的
@api_view
装饰器。 - 基于类视图的
APIView
类。
这些视图封装提供了一些功能,例如确保视图能够接受的Request实例,将上下文添加到Response对象,使得内容协商可以正常运作。
视图封装还内置了一些行为,例如在适当的时候返回405 Method Not Allowed
相应,并处理错误访问的输入request.data
时触发的任何ParseError
异常。
示例
将上面示例的视图函数代码修改为使用@api_view
装饰器
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
@api_view(["GET", "POST"])
def snippet_list(request, format=None):
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, format=None):
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)
示例中每个视图函数中都多了一个format=None
的参数,表示可以将格式后缀的支持添加到API站点,例如http://127.0.0.1:8000/snippets.json
,可以得下图所示的内容:

更新编写的snippets
目录下的urls.py
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views
urlpatterns = [
path("snippets/", views.snippet_list),
path("snippet/<int:pk>/", views.snippet_detail)
]
urlpatterns = format_suffix_patterns(urlpatterns)