django rest framework快速入门第二章 请求与响应

第二章 请求与响应

写在前面:
本文翻译于django rest framework官方文档,由于网上大多数django rest framework中文翻译文档都有较为多的删减行为,笔者在学习的时候就觉得不是太方便,故笔者将官方文档较为完善的为大家翻译下,仅供大家学习参考。

由于笔者文笔有限,若有写得不当之处,敬请各位同仁指出;若涉及到侵权,请联系笔者,笔者将立即删除。

在这一部分中,我们将真正的开始覆盖到REST Framework的核心知识,我们先来介绍几个基本的模块。


1. 请求对象

REST Framework引入了一个Request对象,它扩展了常规的HttpRequest对象,并且提供了更加灵活的请求解析。Request对象的核心功能是request.data属性,它类似于Django常规的request.POST,但对于web API来说,它更加有用。在后面的内容中你们就会体会到这一点。

request.POST  # 仅仅处理表单数据,仅适用于‘POST’方法
request.data  # 处理任意的数据,适用于'POST', 'PUT' 和 'PATCH'方法

另外,使用GET方法请求数据在REST Framework里我们使用request.query_params来获取。

2. 响应对象

REST Framework引入了一个Response对象,他啊是一种TemplateResponse,它接受未渲染的内容,并且使用内容协商来确定返回到客户端的正确的内容类型。

return Response(data)   # 根据客户端的请求来返回正确的内容类型(content type)

3. 状态码

在视图中使用HTTP状态码并不很好的有利于阅读,非常容易就会搞不清状态码是否写错(比如该写404的写成了405),所以,REST Framework为每个状态码提供了更加明显的标识符,但如果你英文不好的话也没办法了。比如HTTP_400_BAD_REQUEST总比400更好懂一些。

4. 装饰API视图

REST Framework提供了两种方法来写API视图

  1. 使用@api_view装饰器来处理基于函数的视图
  2. 使用APIView类来处理基于类的视图

这些包装器提供了几个功能,例如确保在您的视图中接收Request实例,并将上下文添加到Response对象,方便执行内容协商。

包装器还提供一些行为,例如在适当时返回405 Method Not Allowed的响应,以及处理request.data有格式错误时发生的任何ParseError异常。


5. 用这些新的组件来写几个视图

我们不再需要在views.py文件中使用JSONResponse类,所以可以把之前写的这个注释掉,然后重构我们的视图。

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

# 支持’GET‘和’POST‘方法
@api_view(['GET', 'POST'])
def snippet_list(request):
    """
    列出所有的实例或者创建一个新的实例
    """
    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)

这个视图是对我们在上一章节的视图的改进。这个视图明显更加简洁,同时我们使用带有说明的状态码,这使得响应的意义更加明显。

下面我们再写一个视图函数,来对我们单个的实例进行操作。

# 支持‘GET’,‘PUT’和’DELETE‘方法
@api_view(['GET', 'PUT', 'DELETE'])     
def snippet_detail(request, pk):
    """
    检索,更新和删除实例
    """
    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 Framework将响应呈现给我们正确的内容类型。


6. 在我们的URL中添加可选的格式后缀

为了利用我们的响应不再硬连接到单个内容类型,我们可以为我们的API端点添加格式后缀支持。 使用格式后缀为我们提供了明确引用给定格式的网址,这意味着我们的API可以处理像http://example.com/api/items/4.json这样的网址。

首先向这两个视图添加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'^snippets/(?P[0-9]+)$', views.snippet_detail),
]

urlpatterns = format_suffix_patterns(urlpatterns)

添加额外的URL模式不是必须的,但使用它我们可以用一种干净,简单的方式来引用某个特定的格式。

7. 我们该检验我们的成果了

我们和第一章相比,当我们发送一些无效的请求之后,我们将得到更好的错误处理了。

首先,把程序跑起来,然后进入127.0.0.1:8000/snippets/,我们江看到

[
  {
    "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 header来控制回传的格式。

http://127.0.0.1:8000/snippets/ Accept:application/json  # 请求 JSON
http://127.0.0.1:8000/snippets/ Accept:text/html         # 请求 HTML

或者直接附加一个格式后缀

http://127.0.0.1:8000/snippets.json  # JSON 后缀
http://127.0.0.1:8000/snippets.api   # 可浏览的 API 后缀

同样,我们可以使用Content-Type头来控制我们发送的请求的格式。

# 使用表单POST数据
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"
}

# 使用JSON来POST数据
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,你将看到请求的类型在请求头里。


8. 可浏览性

因为API基于客户端请求选择响应的内容类型,所以当Web浏览器请求资源时,它将默认返回资源的HTML格式表示。 这允许API返回完全可web浏览的HTML表示。

拥有一个可以浏览网页的API在可用性方面是一个巨大的胜利,并使开发和使用您的API更容易。 它还显着降低了想要检查和使用您的API的其他开发人员的入口。

有关可浏览的API功能以及如何对其进行自定义的详细信息,请参阅browsable api主题。

9. 下一步

在第三章,我们将开始使用基于类的视图,并且使用通用视图来进一步减少我们的代码量。

谢谢各位阅读,并欢迎各位留下宝贵意见

你可能感兴趣的:(django rest framework快速入门第二章 请求与响应)