本文是我对DRF官网的翻译,并做一些学习笔记。翻译的不是很好,如果有看不懂的建议可以先看看原文,欢迎指正。
原文:2 - Requests and Responses- Django REST framework
从现在开始我们要准备开始接触REST框架的核心部分了。让我们介绍几个基本的构建块。
请求对象Request objects
REST框架引入的Request
对象是对常规DjangoHttpRequest
对象的扩展,也提供了更灵活的请求解析。Resquest
对象的核心功能是request.data
属性,它和reqeust.POST
很像,但是对于WebAPI来说更有用。
request.POST # 只处理表单数据,只对POST方法有用
request.data # 处理任意数据,对POST、PUT、PATCH都有用
响应对象Response objects
REST框架还引入了Response
对象,它是一种TemplateResponse
类型,它接受未渲染的内容并使用协商来确定正确的内容类型以返回给客户端。
return Response(data) # Renders to content type as requested by the client.
状态码
在视图中使用数字 HTTP 状态代码并不总能一目了然,而且如果得到错误代码,很容易忽视。 REST框架为每个状态代码提供了更明确的标识符,例如状态模块中的HTTP_400_BAD_REQUEST
。最好使用这些而不是使用数字标识符。
包装API视图
REST框架提供了两个装饰器,用来写API视图。
-
@api_view
装饰器,用来处理基于函数的视图 -
APIView
类,用来处理基于类的视图
这些包装提供了一些功能,例如确保您在视图中接收到Request
实例,然后向Response
对象中添加上下文,以便可以执行内容协商。
这些包装也提供了返回405 Method Not Allowed
响应的行为,然后在收到request.data
异常数据时处理ParseError
异常。
把它们组装起来
好了,现在我们开始用这些新的组件来重构视图。
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 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)
这对于先前的例子来说,有了一些提升。这更清晰一些,也和Django的Forms API更为类似。这里也使用了具名状态码,让返回值的意义更明确。
以下是views.py
模块中单个snippet的视图。
@api_view(['GET', 'PUT', 'DELETE'])
def snippet_detail(request, pk):
"""
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)
这应该很熟悉,和常规的Django视图差别不大。
我们不再显式地将请求或响应绑定到给定的内容类型。request.data
可以处理即将到来的json
请求,也可以处理其他的格式。类似的,响应对象也会被REST框架渲染成正确的格式。
向URL添加可选的格式后缀
响应不再和单一的内容类型绑定,为了发挥出这个优势,我们为API端点添加对格式后缀的支持。使用格式后缀让URL明确地指向给定的格式,这意味着我们的API可以处理像http://example.com/api/items/4.json
这样的URL。
给我们的两个视图加上fomat
参数,像这样:
def snippet_list(request, format=None):
和
def snippet_detail(request, pk, format=None):
现在更新snippets/urls.py
文件,向已有的URL添加一些额外的format_suffix_patterns
。
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)
没有必要把这些额外的URL样式添加进来,不过这为特定的格式提供了一个简单、明了的方式。
现在看起来如何
像tutorial part 1一样,继续在命令行里测试。虽然我们提供了更好的错误处理非法请求的方式,但一切都非常相似。
我们可以像之前一样,得到一个所有代码片段的列表。
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
相似的,我们可以用Content-Type
来控制请求的格式。
# 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"
}
如果对上面的http
加了--debug
参数,那么就能看到请求头里的请求类型了。
现在打开浏览器,浏览一下http:/127.0.0.1:8000/snippets/
吧。
可浏览性
由于API会根据客户端请求选择响应的内容类型,因此默认情况下,当 Web 浏览器请求该资源时,它将返回资源的 HTML 格式表示。这允许 API 返回一个完全可通过 Web 浏览的 HTML 表示。
拥有一个可浏览网页的 API 好处非常多,并使开发和使用你的 API 变得更加容易。它还显著降低了其他想要检查和使用您的 API 的开发人员的进入门槛。
有关可浏览 API 功能以及如何自定义它的更多信息,请参阅可浏览browsable api。
下一步是什么?
在tutorial part 3,我们会开始使用基于类的视图,然后看看通用视图是如何减少我们的代码量的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。