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.
- The
@api_viewdecorator for working with function based views. - The
APIViewclass 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.
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.g ...
- django rest_framework入门三-Requests和Responses
这一节,我们介绍rest_framework的Requests和Responses对象,来替代django.http的HttpRequest和HttpResponse对象 1.Requests和Res ...
- API(二)之Requests and Responses
这一部分可以让返回的api信息以两种格式呈现:.json和.api REST框架的核心部分.我们来介绍几个基本的组成部分. Request objects REST框架引入了Request对象来扩展常 ...
- [Reactive Programming] Async requests and responses in RxJS
We will learn how to perform network requests to a backend using RxJS Observables. A example of basi ...
- Servlet & JSP - Decorating Requests and Responses
Servlet API 提供了四个包装类:ServletRequestWrapper.ServletResponseWrapper.HttpServletRequestWrapper.HttpServ ...
- Java Servlet (1) —— Filter过滤请求与响应
Java Servlet (1) -- Filter过滤请求与响应 版本: Java EE 6 参考来源: Oracle:The Java EE 6 Tutorial: Filtering Reque ...
- [转]Open Data Protocol (OData) Basic Tutorial
本文转自:http://www.odata.org/getting-started/basic-tutorial/ Basic Tutorial The Open Data Protocol (ODa ...
- RestTemplate实践
什么是RestTemplate? RestTemplate是Spring提供的用于访问Rest服务的客户端,RestTemplate提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效 ...
- Burp Suite教程(英文版)
In this article, we are going to see another powerful framework that is used widely in pen-testing. ...
随机推荐
- 《转》理解Object.defineProperty的作用
对象是由多个名/值对组成的无序的集合.对象中每个属性对应任意类型的值.定义对象可以使用构造函数或字面量的形式: var obj = new Object; //obj = {} obj.name = ...
- Unity3D for VR 学习(3): 暴风魔镜PC Input小改造–自己动手、丰衣足食
在做手游的时候,80%时间是在PC调试的,例如业务逻辑.AI算法.核心玩法等. 拿到魔镜提供的demo,晕了,必须得安装到Android机器上,才能调试,究其原因,有三: 需要用到手机陀螺仪 需要用到 ...
- BZOJ1367 [Baltic2004]sequence 【左偏树】
题目链接 BZOJ1367 题解 又是一道神题,, 我们考虑一些简单的情况: 我们先假设\(b_i\)单调不降,而不是递增 对于递增序列\(\{a_i\}\),显然答案\(\{b_i\}\)满足\(b ...
- [HNOI2006]最短母串问题——AC自动机+状压+bfs环形处理
Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最短的字符串T,使得这n个字符串(S1,S2,„,Sn)都是T的子串. 32MB Input 第一行是一个正整数n(n< ...
- [CF1087D]Minimum Diameter Tree
link 题目大意 有$n$个点的前边权为$0$的树,你要加入$S$边权总量,可以为分数,使得当前树的直径最小. 题目分析 题目过于毒瘤,导致于最后$1$个小时一直在做此题,没想到真的只是一个结论一样 ...
- mysql四-2:多表查询
一 介绍 本节主题 多表连接查询 复合条件连接查询 子查询 准备表 #建表 create table department( id int, name varchar(20) ); create ta ...
- Django summernote 富文本
Summernote is a simple WYSIWYG editor. GITHUB:https://github.com/summernote/django-summernote SETUP ...
- 图像处理之均值滤波介绍及C算法实现
1 均值滤波介绍 滤波是滤波是将信号中特定波段频率滤除的操作,是从含有干扰的接收信号中提取有用信号的一种技术. 均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临 ...
- opencv函数制作的秒针模型
曾经做过,没想到这次再次写这篇代码却用了这么久的时间.这回我要记住他. #include"cv.h" #include"highgui.h" int main( ...
- 前端端对端测试:基于PhantomJS的CasperJS
简介 Casperjs是一个基于PhantomJS和SlimerJS的前端端对端测试框架,当然你也可以使用它完成网络爬虫功能,它的特点的通过简单的脚本模拟浏览器行为, 主要有casper.tester ...