• 2,请求和响应


    From this point we're going to really start covering the core of REST framework. Let's introduce a couple of essential building blocks.

    从现在起,我们将开始接触 REST 框架的核心。首先介绍一些基本的模块。

    Request objects

    请求对象

    REST framework introduces a Request object that extends the regular HttpRequest, and provides more flexible request parsing. The core functionality of the Request object is the request.DATA attribute, which is similar to request.POST, but more useful for working with Web APIs.

    REST 框架有个继承自原生 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.

    Response objects

    响应对象

    REST framework also introduces a Response object, which is a type of TemplateResponse that takes unrendered content and uses content negotiation to determine the correct content type to return to the client.

    REST 框架也引入了一个响应对象,它继承自TemplateResponse对象,它获得未渲染的内容并通过内容协商content negotiation 来决定正确的content type返回给client。

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

    Status codes

    状态码

    Using numeric HTTP status codes in your views doesn't always make for obvious reading, and it's easy to not notice if you get an error code wrong. REST framework provides more explicit identifiers for each status code, such as HTTP_400_BAD_REQUEST in the status module. It's a good idea to use these throughout rather than using numeric identifiers.

    使用数字状态码不利于阅读代码,如果代码有错误不好定位。REST 框架为每个状态码提供了更加清晰的标示,如 HTTP_400_BAD_REQUEST 。相比于使用数字,在整个views中使用这类标识符将更好。

    Wrapping API views

    包装API视图函数

    REST framework provides two wrappers you can use to write API views.

    REST 框架提供两个包装函数用于写API视图

    1. The @api_view decorator for working with function based views.
    2. The APIView class for working with class based views.
    • @api_view 装饰器,用于函数级别。
    • APAIView 类, 用于类级别。

    These wrappers provide a few bits of functionality such as making sure you receive Request instances in your view, and adding context to Response objects so that content negotiation can be performed.

    这两种封装器提供了许多功能,例如,确保在view当中能够接收到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.

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

    Pulling it all together

    汇总

    Okay, let's go ahead and start using these new components to write a few views.

    We don't need our JSONResponse class in views.py anymore, so go ahead and delete that. Once that's done we can start refactoring our views slightly.

    我们开始用这些新的组件来写一些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, 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)

    Our instance view is an improvement over the previous example. It's a little more concise, and the code now feels very similar to if we were working with the Forms API. We're also using named status codes, which makes the response meanings more obvious.

    Here is the view for an individual snippet, in the views.py module.

    上面的代码是对我们之前代码的改进。看上去更简洁,也更类似于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)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
        elif request.method == 'DELETE':
            snippet.delete()
            return Response(status=status.HTTP_204_NO_CONTENT)

    This should all feel very familiar - it is not a lot different from working with regular Django views.

    这些非常地熟悉,因为它们没有和原生的Django视图函数有什么大的不同。

    Notice that we're no longer explicitly tying our requests or responses to a given content type. request.DATA can handle incoming json requests, but it can also handle yaml and other formats. Similarly we're returning response objects with data, but allowing REST framework to render the response into the correct content type for us.

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

    Adding optional format suffixes to our URLs

    给URLs增加可选的格式后缀

    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.

    Start by adding a format keyword argument to both of the views, like so.

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

    在视图函数中增加format参数,如:

    def snippet_list(request, format=None):

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

    Now update the urls.py file slightly, to append a set of format_suffix_patterns in addition to the existing URLs.

    现在稍微改动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)

    We don't necessarily need to add these extra url patterns in, but it gives us a simple, clean way of referring to a specific format.

    这些额外的url patterns并不是必须的,只是为了简单的说明指定格式的渲染方法。

    How's it looking?

    怎样看结果

    Go ahead and test the API from the command line, as we did in tutorial part 1. Everything is working pretty similarly, although we've got some nicer error handling if we send invalid requests.

    We can get a list of all of the snippets, as before.

    在终端中键入:

    curl http://127.0.0.1:8000/snippets/
    
    [
    {
    "id": 1, "title": "", "code": "foo = "bar" ", "linenos": false, "language": "python", "style": "friendly"},
    {"id": 2, "title": "", "code": "print "hello, world" ", "linenos": false, "language": "python", "style": "friendly"}
    ]

    We can control the format of the response that we get back, either by using the Accept header:

    我们可以通过 Accept Header 来控制响应格式:

    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

    Or by appending a format suffix:

    或者添加URL的后缀方式来指定响应格式:

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

    Similarly, we can control the format of the request that we send, using the Content-Type header.

    类似的,我们可以控制发送请求的格式,通过 Content-Type header 来实现:

    # POST using form data
    curl -X POST http://127.0.0.1:8000/snippets/ -d "code=print 123"
    
    {"id": 3, "title": "", "code": "print 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/.

    现在可以通过浏览器来查看结果。

    Browsability

    可使用浏览器

    Because the API chooses the content type of the response based on the client request, it will, by default, return an HTML-formatted representation of the resource when that resource is requested by a web browser. This allows for the API to return a fully web-browsable HTML representation.

    因为 API 是基于客户端的请求来选择响应格式,所有,默认地,如果是通过浏览器来请求数据,那么响应格式为 HTML。

    Having a web-browsable API is a huge usability win, and makes developing and using your API much easier. It also dramatically lowers the barrier-to-entry for other developers wanting to inspect and work with your API.

    拥有一个浏览器可使用的 API 是非常有用的,它利于开发和让API使用起来跟简单。它也会显著的降低与其他开发者的阻隔。

    See the browsable api topic for more information about the browsable API feature and how to customize it.

    更多关于浏览器可使用API,请到此处browsable api

    What's next?

    接下来,我们将开始使用基于类的视图函数,你将会看到类视图函数会让代码更加的简洁。

    In tutorial part 3, we'll start using class based views, and see how generic views reduce the amount of code we need to write.

  • 相关阅读:
    [题解] P2513 [HAOI2009]逆序对数列
    [题解]洛谷P2709 小B的询问
    题解 P1944 最长括号匹配_NOI导刊2009提高(1)
    [题解]SP703 SERVICE
    Bzoj2427: [HAOI2010]软件安装
    【题解】UVA11362 Phone List
    【题解】P2922 [USACO08DEC]秘密消息Secret Message
    Tire树的学习
    【题解】P1171 售货员的难题
    计算机与编程资源教程汇总
  • 原文地址:https://www.cnblogs.com/nigang/p/3755233.html
Copyright © 2020-2023  润新知