django-rest-framework指南:Requests and Responses
Posted 黑猫-警长
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了django-rest-framework指南:Requests and Responses相关的知识,希望对你有一定的参考价值。
Tutorial 2: Requests and Responses
我要开始接触REST framework的核心了.先介绍一些基本的组件.
Request objects
REST framework引进了一个继承自HttpRequst的Request对象,并提供了更灵活的请求解析.Request对象的核心功能时request.data属性,它和request.POST有点相似,但更适合于WEB API.
request.POST # 只获取表单数据,只能用于POST方法
request.data # 获取所有数据,能用于POST,PUT和PATCH方法
Response objects
REST framework也引进了Response对象,它是TemplateResponse类型的,通过未渲染内容和内容协议(content negotiation)来决定返回到客户端的正确的content type.
return Response(data) # 根据客户端的请求来渲染content type
Status codes
在视图里使用HTTP状态码通常不易于代码阅读,写错状态码也不容易发现.REST framework为每个状态码提供了更显式的标识,比如status模块里的HTTP_404_BAD_REQUEST.使用他们比使用数字的状态码要好.
Wrapping API views
REST framework提供了2种wrapper用于写API视图.
1. @api_view装饰器,用于视图函数.
2. APIView类,用于视图类.
这些wrapper提供了一些功能,例如确保在视图中能接受Request实例,并将内容添加到Response对象,这样就能完成内容协议(content negotiation).
这些wrapper也提供了一些动作(behaviour),例如适当的时候响应405 Method Not Allowed,当解析的request.data格式不正确时抛出ParseError异常.
Pulling it all together
ok,让我们开始利用这些新组件来写一些视图.
我们不再需要JSONResponse类和views.py了,所以请删除.然后我们开始慢慢重构我们的视图.
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):
'''
列出所有snippet,或者创建一个新的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=HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
这是对上一个例子的改进的view.稍微简洁了点,感觉和Form API有点像.我们也使用了命名的状态码,使响应的意思更明显.
下面是views.py模块中,针对单个的snippet的代码.
@api_view(['GET', 'PUT', 'DELETE'])
def snippet_detail(request, pk):
'''
查找,更新或删除一个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视图没有很多不同.
注意:我们不再需要显式的声明请求或相应的content type.request.data能处理json请求,同样也能处理其他格式.同样的返回带有数据的响应对象,REST framework能为我们用正确的格式渲染响应.
Adding optional format suffixed to our URLs(为URL添加可选的format后缀)
To take advantage of the fact that our responses are no longer hardwired to a single content type let’s add support for format suffixes to our API endpoints. Using format suffixes gives us URLs that explicitly refer to a given format, and means our API will be able to handle URLs such as http://example.com/api/items/4/.json.
在view里添加关键字参数format,就像这样.
def snippet_list(request, format=None):
和
def snippet_detail(request, pk, format=None):
稍微改下urls.py文件,在现有的URL里添加format_suffix_patterns.
from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views
urlpatterns = [
url(r'^snippets/$', views.snippet_list),
url(r'^sinppets/(?P<pk>[0-9]+)/$', views.snippets_detail),
]
urlpatterns = format_suffix_patterns(urlpatterns)
不是一定要这样使用,但是这种方法简洁实用.
How is it looking?
就像在指南(1)中做的那样,我们来测试一下API.一切都很相似,而且如果发送了无效的请求也有错误处理了.
我们会获得一个snippet列表,就像之前
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
或者用format后缀:
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://127.0.0.1:8000/snippets/,就可以在浏览器里打来API了.
Browsability
因为API是根据客户端请求来确定相应的内容格式(content type),所以如果用浏览器,默认情况下返回HTML格式的资源.
web-browsable API易于使用,能使开发和使用API更容易.这能使其他开发者查看和使用你的API更方便,简单.
What is next?
在指南(3),我们将使用视图类,这样能少些很多代码.
以上是关于django-rest-framework指南:Requests and Responses的主要内容,如果未能解决你的问题,请参考以下文章
django-rest-framework指南:Class Based Views(类视图)
在 django-rest-framework 中插入 django-allauth 作为端点
如何将命名空间 url 添加到 django-rest-framework 路由器视图集
django-rest-framework:如何序列化已经包含 JSON 的字段?