REST框架引入了Request对象来扩展常规的HttpRequest,并提供更灵活的请求解析。Request对象的核心功能是request.data属性,这与request.POST相似,但对使用Web API更有用。
request.POST # Only handles form data. Only works for ‘POST‘ method. request.data # Handles arbitrary data. Works for ‘POST‘, ‘PUT‘ and ‘PATCH‘ methods.
REST框架还引入了一个Response对象,它是TemplateResponse的一种类型,它使用未渲染的内容,并使用内容协商来确定正确的内容类型以返回给客户端。
return Response(data) # Renders to content type as requested by the client.
在您的视图中使用数字HTTP状态码并不总是利于阅读,如果您收到 an error code wrong你将很难注意到。 REST框架为每一个状态码更明确的标识符,如status模块中的HTTP_400_BAD_REQUEST。 使用这些标识符比使用数字标识符要好的多。
REST框架提供了两个可用于编写API视图的wrappers。
The @api_view 装饰器对function-based views有效。
The APIView class对class-based views有效。
这些wrappers提供了一些功能,例如确保您在视图中接收Request实例,并将上下文添加到Response对象,以便可以执行content negotiation。
The wrappers also provide behaviour such as returning 405 Method Not Allowed responses when appropriate, and handling any ParseError exception that occurs when accessing request.data with malformed input.
好的,我们开始使用这些新的组件来写几个视图。
views.py中不再需要JSONResponse class, 所以请删除它。一旦完成这些,我们就可以开始重构我们视图了.
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): """ List all 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)
我们的实例视图比以前的例子有所改进。这更加简明扼要,现在的代码与我们使用的Forms API非常相似。我们还使用命名的状态码,,这使得响应意义更加明显。
以下是views.py模块中单个的代码段视图。
@api_view([‘GET‘, ‘PUT‘, ‘DELETE‘]) def snippet_detail(request, pk): """ Retrieve, update or delete a snippet instance. """ 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)
这应该都是非常熟悉的 - 与常规的Django视图并没有什么不同。
请注意,我们不再明确地将我们的请求或响应绑定到一个给定的内容类型。request.data 能够处理输入的 json requests,但它也可以处理其他格式。同样,我们使用数据返回响应对象,但允许REST框架将响应渲染成正确的内容类型。
我们的响应不再与单一内容类型连接,为了充分利用这个事实,我们可以为API端点添加一些格式后缀。使用格式后缀给urls明确指定一个格式,这意味着我们的API将能够处理诸如之类的urls。
首先在两个视图中添加一个format关键字参数,就像这样。
def snippet_list(request, format=None):
and
def snippet_detail(request, pk, format=None):
Now现在稍微更新urls.py文件,另外给已经存在的urls附加一组format_suffix_patterns。