返回目錄
上一節(jié): 序列化器
從現(xiàn)在開始我們將要真正涉及到REST framework的核心部分, 讓我們先介紹幾個(gè)基本構(gòu)建塊吭敢。
Request 對象
REST框架引入了一個(gè)Request對象碰凶,該對象擴(kuò)展了常規(guī)的HttpRequest,并提供了更靈活的請求解析鹿驼。Request對象中的一個(gè)核心功能就是request.data
屬性欲低,與request.POST
十分類似,但是在使用Web API的時(shí)候更加有用畜晰。
request.POST # 只能處理數(shù)據(jù)砾莱, 只在POST請求時(shí)起作用。
request.data # 處理任意數(shù)據(jù)凄鼻,在POST, PUT, PATCH請求下都起作用
Response 對象
REST framework 也提供了Response對象腊瑟,它是SimpleTemplateResponse
的一個(gè)子類聚假,接收未經(jīng)渲染的內(nèi)容,并根據(jù)前端要求的格式轉(zhuǎn)換成正確格式內(nèi)容闰非,返回給客戶端膘格。
return Response(data) # Renders to content type as requested by the client.
狀態(tài)碼
在視圖中使用數(shù)字狀態(tài)碼讀起來并不是很清晰,并且很容易將狀態(tài)碼用混财松,REST framework 提供了更明確定義的狀態(tài)碼瘪贱,比如status
模塊中的HTTP_400_BAD_REQUEST
,使用這些狀態(tài)碼而不是使用純數(shù)字的狀態(tài)碼是更好的選擇辆毡。
包裝API 視圖
REST framework提供了兩種包裝視圖API的方法菜秦。
1. @api_view
裝飾器可以使用在基于函數(shù)的視圖上。
2. APIView
類可以使用在基于類的視圖上胚迫。
他們提供了一些使用的方法喷户,比如確保視圖函數(shù)接收到了Request
實(shí)例,并且給Response
對象添加上下文访锻,以確保內(nèi)容正確的渲染褪尝。
包裝方法還會在合適的時(shí)候響應(yīng)405 Method Not Allowed
,也會在輸入的數(shù)據(jù)不完整的時(shí)候期犬,處理ParseError
異常河哑。
組合到一起
OK!現(xiàn)在開始使用這些新組件寫幾個(gè)視圖函數(shù)吧龟虎。
我們在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
@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)
我們的視圖較之前的版本有了一些升級佳吞,更加簡潔,而且如果了解Form的API的話棉安,對現(xiàn)在的代碼會似曾相識底扳。我們使用了命名過的狀態(tài)碼,他們使響應(yīng)看起來更加的清晰贡耽,更加語義化衷模。
下面是訪問單獨(dú)代碼片段的視圖函數(shù),同樣也在views.py
中蒲赂。
@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)
一切看起來都那么熟悉阱冶,這與Django常規(guī)的視圖并沒有太大的區(qū)別。
注意我們不再明確地將我們的請求或響應(yīng)綁定到給定的內(nèi)容類型滥嘴。request.data
可以處理傳入的json
請求木蹬,但它也可以處理其他的格式。類似地若皱,我們返回帶有數(shù)據(jù)的響應(yīng)對象届囚,但允許REST framework將內(nèi)容渲染成正確的類型有梆。
給URL添加可選的格式化后綴
在API的最后,添加格式化后綴意系,可以讓我們體驗(yàn)到不再將響應(yīng)與唯一的內(nèi)容格式綁定的好處,使用格式化后綴可以讓我們通過url來明確地指定需要返回的類型饺汹,這意味著你可以這樣寫urlhttp://example.com/api/items/4.json
蛔添。
首先在視圖中添加format
關(guān)鍵字參數(shù)。
def snippet_list(request, format=None):
還有:
def snippet_detail(request, pk, format=None):
現(xiàn)在稍微修改snippets/urls.py
兜辞,除了現(xiàn)有的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<pk>[0-9]+)$', views.snippet_detail),
]
urlpatterns = format_suffix_patterns(urlpatterns)
我們不一定需要添加這些額外的urlpatterns
毕骡,但它為我們提供了一種簡單验辞,干凈的方式來引用特定的格式。
效果
盡管使用命令行工具來測試我們的API吧荣瑟,一切看起來和之前一樣扫皱,雖然我們發(fā)送無效請求的話足绅,會有以下更好的錯(cuò)誤處理。
我們能獲取到所有的代碼片段韩脑,和之前一樣氢妈。
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"
}
]
我們可在請求頭中使用Accept
字段來控制響應(yīng)中的格式:
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
或者通過添加格式化后綴:
http http://127.0.0.1:8000/snippets.json # JSON suffix
http http://127.0.0.1:8000/snippets.api # Browsable API suffix
同樣,我們也可以使用請求頭中的Content-Type
字段聲明請求中的數(shù)據(jù)格式段多。
# 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"
}
如果你在http
請求之前添加了--debug
選項(xiàng)首量, 你就可以在請求頭中看到請求的類型了。
現(xiàn)在在瀏覽器中輸入http://127.0.0.1:8000/snippets/ 來打開API进苍。
瀏覽功能
由于API根據(jù)客戶端請求中指定的格式響應(yīng)內(nèi)容類型加缘,當(dāng)使用瀏覽器請求資源的時(shí)候,API會默認(rèn)將資源渲染成HTML的格式觉啊,得到一個(gè)完整的可瀏覽的HTML表現(xiàn)形式拣宏。
擁有可瀏覽的API時(shí)一個(gè)十分有用的功能,使開發(fā)和使用API變得十分容易柄延,同時(shí)也降低了其他檢查或使用你的API的開發(fā)者的準(zhǔn)入門檻蚀浆。
查看(The Browsable API )獲取可瀏覽API的更多信息,并了解如果自定義搜吧。
下一步市俊?
在教程3中,我們要學(xué)習(xí)基于類的視圖滤奈,并了解generic view
怎樣節(jié)約我們的代碼量摆昧。