请求和响应 Requests and Responses
从这一片来说,我们将真正开始覆盖REST框架的核心。我们来介绍一些基本的构建块
Request objects
REST框架引入了一个Request扩展常规的对象HttpRequest,并提供更灵活的请求解析。Request对象的核心功能是request.data,和之类似的属性request.POST,但比request.POST更为有用。
request.POST # Only handles form data. Only works for 'POST' method.
request.data # Handles arbitrary data. Works for 'POST', 'PUT' and 'PATCH' methods.
Response objects
REST框架还引入了一个Response对象,它是一种类型的对象,它TemplateResponse使用未呈现的内容并使用内容协商来确定返回给客户端的正确内容类型。
return Response(data) # Renders to content type as requested by the client.
状态码
在视图中使用数字HTTP状态代码并不易见的阅读,并且如果代码错误,并不很容易注意到。REST框架为每个状态代码提供更明确的标识符,例如HTTP_400_BAD_REQUEST在status模块中。这是一个好主意,而不是使用数字标识符。
封装的API视图
REST框架提供了两个可用于编写API视图的包装器。
@api_view用于处理基于函数的视图的装饰器。
该APIView班与基于类的视图工作。
这些包装提供了一些功能,例如确保Request在视图中接收实例,并向Response对象添加上下文,以便可以执行内容协商。
这些包装器还提供了一些行为,例如405 Method Not Allowed在适当时返回响应,以及处理ParseError在request.data格式错误的输入中访问时发生的任何异常。
实战
好的,让我们继续,开始使用这些新的组件。
让我们重新编写上面关于序列化的项目,重新编写上面view里面的内容
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
@api_view(['GET', 'POST'])
def snippet_list(request, format=None):
"""
List all code snippets, or create a new snippet.
"""
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):
"""
Retrieve, update or delete a code snippet.
"""
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)
测试
http http://127.0.0.1:8000/snippets/
HTTP/1.1 200 OK
...
[
{
"id": 1,
"title": "",
"code": "foo = \"bar\"\n",
"linenos": false,
"language": "python",
"style": "friendly"
},
{
"id": 2,
"title": "",
"code": "print \"hello, world\"\n",
"linenos": false,
"language": "python",
"style": "friendly"
}
]
我们可以通过使用Accept头来控制返回的响应的格式
http http://127.0.0.1:8000/snippets/ Accept:application/json # Request JSON
http http://127.0.0.1:8000/snippets/ Accept:text/html # Request HTML
或者通过附加格式后缀
http http://127.0.0.1:8000/snippets.json # JSON suffix
http http://127.0.0.1:8000/snippets.api # Browsable API suffix
# POST using form data
http --form POST http://127.0.0.1:8000/snippets/ code="print 123"
{
"id": 3,
"title": "",
"code": "print 123",
"linenos": false,
"language": "python",
"style": "friendly"
}
# POST using JSON
http --json POST http://127.0.0.1:8000/snippets/ code="print 456"
{
"id": 4,
"title": "",
"code": "print 456",
"linenos": false,
"language": "python",
"style": "friendly"
}