從本節我們開始真正接觸rest framework的核心部分。首先我們學習一下一些必備知識。
1. Request Object ——Request對象
rest framework 引入了一個繼承自HttpRequest的Request對象,該對象提供了對請求的更靈活解析。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_REQUEST。相比於使用數字,在整個views中使用這類標識符將更好。
4. 封裝API views
在編寫API views時,REST Framework提供了兩種wrappers:
1). @api_viwe 裝飾器 ——函數級別
2). APIView 類——類級別
這兩種封裝器提供了許多功能,例如,確保在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並不是必須的。
來源:
http://django-rest-framework.org/tutorial/2-requests-and-responses.html