DRF向导之请求和响应

src

从本节我们开始真正接触rest framework的核心部分。首先我们学习一下一些必备知识。


1. Request Object ——Request对象

​ rest framework 引入了一个继承自HttpRequestRequest对象,该对象提供了对请求的更灵活解析。request对象的核心部分是request.DATA属性,类似于request.POST, 但在使用WEB API时,request.DATA更有效。

request.POST # Only handles form data. Only works for ‘POST’ method.
request.DATA # Handles arbitrary data. Works any HTTP request with content.



2. Response Object ——Response对象

​ rest framework引入了一个Response 对象,它继承自TemplateResponse对象。它获得未渲染的内容并通过内容协商content negotiation 来决定正确的content type返回给client。

return Response(data)  # Renders to content type as requested by the client.

3. Status Codes

​ 在views当中使用数字化的HTTP状态码,会使你的代码不宜阅读,且不容易发现代码中的错误。rest framework为每个状态码提供了更明确的标识。例如HTTP_400_BAD_REQUESTstatus module。相比于使用数字,在整个views中使用这类标识符将更好。



4. 封装API views

​ 在编写API views时,REST Framework提供了两种wrappers:

  1. @api_viwedecorator for working with function based views.
  2. APIView class for working with class based views.

​ 这两种封装器提供了许多功能,例如,确保在view当中能够接收到Request实例;往Response中增加内容以便内容协商content negotiation 机制能够执行。

​ 封装器也提供一些行为,例如在适当的时候返回405 Methord Not Allowed响应;在访问多类型的输入request.DATA时,处理任何的ParseError异常。



5. 汇总

我们开始用这些新的组件来写一些views。

我们不在需要JESONResponse 类(在前一篇中创建),将它删除。删除后我们开始稍微重构下我们的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):
    """
    List all snippets, or create a new snippet.
    """
    if request.method == 'GET':
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets)
        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)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


上面的代码是对我们之前代码的改进。看上去更简洁,也更类似于django的forms api形式。我们也采用了状态码,使返回值更加明确。



下面是对单个snippet操作的view更新:

@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)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

​ 注意,我们并没有明确的要求requests或者responses给出content type。request.DATA可以处理输入的json请求,也可以输入yaml和其他格式。类似的在response返回数据时,REST Framework返回正确的content type给client。



6. 给URLs增加可选的格式后缀

​ 利用在response时不需要指定content type这一事实,我们在API端增加格式的后缀。使用格式后缀,可以明确的指出使用某种格式,意味着我们的API可以处理类似http://example.com/api/items/4.json.的URL。

增加format参数在views中,如:

def snippet_list(request, format=None):

and

def snippet_detail(request, pk, format=None):

现在稍微改动urls.py文件,在现有的URLs中添加一个格式后缀pattterns (format_suffix_patterns):

from django.conf.urls import patterns, url
from rest_framework.urlpatterns import format_suffix_patterns

urlpatterns = patterns('snippets.views',
    url(r'^snippets/$', 'snippet_list'),
    url(r'^snippets/(?P<pk>[0-9]+)$', 'snippet_detail'),
)

urlpatterns = format_suffix_patterns(urlpatterns)
这些额外的url patterns并不是必须的。



7. How’s it looking?

​ 继续从命令行测试api,正如我们在教程第1部分中所做的那样。所有的工作都非常类似,尽管我们在发送无效请求时有更好的错误处理。
​ 我们可以像以前一样得到所有片段的列表。

curl http://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头来控制返回的响应的格式:

curl http://127.0.0.1:8000/snippets/ -H 'Accept: application/json'  # Request JSON
curl http://127.0.0.1:8000/snippets/ -H 'Accept: text/html'         # Request HTML

或附加格式后缀:

curl http://127.0.0.1:8000/snippets/.json  # JSON suffix
curl http://127.0.0.1:8000/snippets/.api   # Browsable API suffix

类似地,我们可以使用内容类型头控制发送的请求的格式

# POST using form data
curl -X POST http://127.0.0.1:8000/snippets/ -d "code=print 123"
{"id": 3, "title": "", "code": "123", "linenos": false, "language": "python", "style": "friendly"}

# POST using JSON
curl -X POST http://127.0.0.1:8000/snippets/ -d '{"code": "print 456"}' -H "Content-Type: application/json"
{"id": 4, "title": "", "code": "print 456", "linenos": true, "language": "python", "style": "friendly"}

Now go and open the API in a web browser, by visiting http://127.0.0.1:8000/snippets/.



8. 可浏览性

由于api基于客户端请求选择响应的内容类型,因此在web浏览器请求资源时,它将默认返回该资源的html格式表示。这允许api返回完全可web浏览的html表示。
拥有一个web可浏览的api是一个巨大的可用性胜利,它使开发和使用api变得更加容易。它还大大降低了其他想要检查和使用您的api的开发人员进入的障碍。
有关可浏览API功能和如何自定义该功能的详细信息,请参阅[可浏览API][可浏览API]主题。

发布了18 篇原创文章 · 获赞 4 · 访问量 2228

猜你喜欢

转载自blog.csdn.net/qq_41996454/article/details/101431858