Tutorial 2: Requests and Responses

转载自:http://www.django-rest-framework.org/tutorial/2-requests-and-responses/

Tutorial 2: Requests and Responses

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

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.

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.

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.

Wrapping API views

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

  1. The @api_view decorator for working with function based views.
  2. The APIView class for working with class-based views.

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.

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.

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 any more, so go ahead and delete that. Once that‘s done we can start refactoring our views slightly.

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)

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.

@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)

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

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 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.

Adding optional format suffixes to our 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.

def snippet_list(request, format=None):

and

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.

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<pk>[0-9]+)$‘, views.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.

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.

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"
  }
]

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

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

Or by appending a format suffix:

http http://127.0.0.1:8000/snippets.json  # JSON suffix
http 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.

# 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"
}

If you add a --debug switch to the http requests above, you will be able to see the request type in request headers.

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.

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.

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

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.

时间: 2024-10-11 02:30:44

Tutorial 2: Requests and Responses的相关文章

02_Tutorial 2: Requests and Responses 请求和响应

1.请求和响应 1.文档 https://www.django-rest-framework.org/tutorial/2-requests-and-responses/ https://q1mi.github.io/Django-REST-framework-documentation/tutorial/2-requests-and-responses_zh/ 2.请求对象:request.data # request.data # 处理任意数据 适用于'POST','PUT'和'PATCH'

API(三)之Requests and Responses

Request objects REST框架引入了Request对象来扩展常规的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

Django-Rest-Framework 教程: 2. Requests 和 Responses

接着上篇的内容, 本篇中, 我们进一步介绍Django-rest-framework的其他核心部件. 首先我们来做准备工作: Request django-rest-framework中引入了新的Request类, 该Request继承自Django的HttpRequest, 并提供了更多灵活的request处理功能. 比如request.DATA属性便是专门用作Web API的属性, 类似于request.POST. request.POST # 只处理form数据; 只接受HTML 'POS

[转]Open Data Protocol (OData) Basic Tutorial

本文转自:http://www.odata.org/getting-started/basic-tutorial/ Basic Tutorial The Open Data Protocol (OData) is a data access protocol built on core protocols like HTTP and commonly accepted methodologies like REST for the web. There are various kinds of

iOS开发资料整理

Please help me contribute to this list, for non-experience iOS developers or someone who need a come-in-handy library list to refer or to use in their projects. Fork, edit and send a PR are all things you can do! Table of Contents UI Component// UI组件

很好的iOS学习资料

https://github.com/vsouza/awesome-ios 汇集了很多好的资料 https://github.com/vsouza/awesome-ios Skip to content This repository Pull requests Issues Gist You don’t have any verified emails. We recommend verifying at least one email. Email verification helps ou

Spring提供的用于访问Rest服务的客户端:RestTemplate实践

什么是RestTemplate? RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率.调用RestTemplate的默认构造函数,RestTemplate对象在底层通过使用java.net包下的实现创建HTTP 请求,可以通过使用ClientHttpRequestFactory指定不同的HTTP请求方式.ClientHttpRequestFactory接口主要提供了两种实现方式

Spring - MVC Framework 教程

Spring - MVC Framework Tutorial 太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. Spring - MVC Framework Tutorial Advertise

性能测试分析软件汇总–开源、商业全部收集

本文共包含:商业性能测试.监控.分析工具和免费.开源性能测试监控分析工具:共涉及java.php.net等各种开发语言平台,有系统性能分析.文件系统分析.微博.系统分析.数据性能分析等各种工具,可以说本文包含了现有的所有的性能测试监控分析工具工具133种. Java程序性能分析工具 VisualVM VisualVM是一个集成多个JDK命令行工具的可视化工具.可以作为Java应用程序性能分析和运行监控的工具.开发人员可以利用它来监控.分析线程信息,浏览内存堆数据.系统管理员可以利用它来监测.控制