DRF嚮導之請求和響應

src

從本節我們開始真正接觸rest framework的核心部分。首先我們學習一下一些必備知識。


1. Request Object ——Request對象

​ rest framework 引入了一個繼承自HttpRequestRequest對象,該對象提供了對請求的更靈活解析。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_REQUESTstatus module。相比於使用數字,在整個views中使用這類標識符將更好。



4. 封裝API views

​ 在編寫API views時,REST Framework提供了兩種wrappers:

  1. @api_viwedecorator for working with function based views.
  2. APIView class for working with class based views.

​ 這兩種封裝器提供了許多功能,例如,確保在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並不是必須的。



7. How’s it looking?

​ 繼續從命令行測試api,正如我們在教程第1部分中所做的那樣。所有的工作都非常類似,儘管我們在發送無效請求時有更好的錯誤處理。
​ 我們可以像以前一樣得到所有片段的列表。

curl http://127.0.0.1:8000/snippets/
[{"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頭來控制返回的響應的格式:

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

或附加格式後綴:

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

類似地,我們可以使用內容類型頭控制發送的請求的格式

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



8. 可瀏覽性

由於api基於客戶端請求選擇響應的內容類型,因此在web瀏覽器請求資源時,它將默認返回該資源的html格式表示。這允許api返回完全可web瀏覽的html表示。
擁有一個web可瀏覽的api是一個巨大的可用性勝利,它使開發和使用api變得更加容易。它還大大降低了其他想要檢查和使用您的api的開發人員進入的障礙。
有關可瀏覽API功能和如何自定義該功能的詳細信息,請參閱[可瀏覽API][可瀏覽API]主題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章