1. 程式人生 > >Django REST framework教程二: 請求和響應

Django REST framework教程二: 請求和響應

教程索引目錄

Django REST framework的系列教程
對於需要通篇瞭解的同學,可以點選教程索引目錄

從現在開始,我們要開始,真正接觸到REST framework的核心部分了。當然,我們需要先認識一些重要的基本元素。

請求物件(Request object)

REST framework引入了一個 Request 物件, 它繼承自普通的 HttpRequest ,但能夠更加靈活的解析收到的請求。Request 物件的核心功能,就是其中的 request.data 屬性。這個屬性跟 request.POST 相似,但對我們的Web API來說,更加的有用。

request.POST  # 只能處理表單(form)資料,只能處理“POST”方法.
request.data # 處理任意資料.可以處理'POST', 'PUT' 和 'PATCH'方法.

響應物件(Response object)

REST framework 同時引入了 Response 物件,是一種 TemplateResponse ,它攜帶著純粹的內容,通過內容協商(Content Negotiation)來決定,將以何種形式,返回給客戶端。

return Response(data)  # 根據客戶端的要求,把內容,生成對應的形式.

狀態碼(Status codes)

在你的視圖裡,使用純數字的狀態碼,並不利於程式碼閱讀,如果你寫錯了狀態碼,也不會很容易的察覺。REST framework為每個狀態碼提供了更加明確的標識,比如 HTTP_400_BAD_REQUEST

,這個識別符號在 status 模組中。我們在各處,使用這種識別符號,而不是純數字的狀態碼,這是個很好的想法。

包裝API檢視(wrapping API views)

REST framework提供了兩種編寫API view的封裝。

  1. 使用 @api_view 裝飾器,基於方法的檢視
  2. 繼承 APIView 類,基於類的檢視

這些檢視封裝,提供了些許的功能,比如:確保你的檢視能夠收到 Request 例項;還有,將內容賦予 Response 物件,使得 內容協商(content negotiation) 可以正常的運作。

檢視封裝,也內建了一些行為,比如:在遇到錯誤請求時,自動響應 405 Method Not Allowed

;在處理 request.data 時,因為輸入的格式不恰當,而發生的任何 ParseError 異常(exception),檢視封裝都會處理。

將所有元素 合起來

現在,讓我們繼續,用這些新的元素來寫幾個檢視。

我們不再需要 view.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):
    """
    列出所有的程式碼片段(snippets),或者建立一個程式碼片段(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)

當前的例項,相比之前的例子,有了改進:它變得,簡潔了一點,並且,如果你曾經使用過Forms API,你會發現,它們非常的相識。我們也用了命名式的狀態碼,這讓響應的狀態,易於閱讀。

下面是snippet的詳細檢視,它在 views.py 模組中。

@api_view(['GET', 'PUT', 'DELETE'])
def snippet_detail(request, pk):
    """
    讀取, 更新 或 刪除 一個程式碼片段例項(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)
        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檢視,沒多大的區別。

值得一提的是,我們已經不再明確地,解析/定義檢視中 Request/Response的內容型別。request.data 會自行處理輸入的json 請求,當然,也能處理別的格式。同樣的,我們只需返回響應物件以及資料,REST framework會幫我們,將響應內容,渲染(render)成正確的格式。

為我們的URLs新增可選的格式字尾

現在,我們的響應,不再硬性繫結在,某一種返回格式上,利用這點優勢,我們可以為API端,新增格式的字尾。使用格式字尾,可以定製我們的URLs,使它明確的指向指定的格式,這意味著,我們的API可以處理一些URLs,類似這樣的格式 http://example.com/api/items/4/.json

首先,需要新增一個 format 關鍵字引數,如下所示:

def snippet_list(request, format=None):

還有:

def snippet_detail(request, pk, format=None):

然後對 urls.py 檔案,做些小改。在現有的URLs基礎上,追加一套 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)

我們不需要逐一地,新增對格式支援的 url 樣式(patterns),這是一個簡潔的方法,來快速支援特定的格式。

效果如何?

接著,我們可以從命令列中測試我們的API,跟教程一tutorial part 1)中的操作一樣。儘管我們對一些無效的請求,提供了很好的處理,但仍然沒有太大的改變。

我們可以獲取所有snippet的列表,就跟之前一樣。

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

我們也可以控制響應內容的格式,通過Http中的 Accept 頭(header):

http http://127.0.0.1:8000/snippets/ Accept:application/json  # 請求 JSON
http http://127.0.0.1:8000/snippets/ Accept:text/html         # 請求 HTML

或通過追加格式字尾(format suffix):

http http://127.0.0.1:8000/snippets.json  # JSON 字尾
http http://127.0.0.1:8000/snippets.api   # 視覺化 API 字尾

同樣的,我們可以控制,傳送的請求型別,通過http中的 Content-Type 頭(header):

# POST 使用表單資料
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 使用 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"
}

視覺化

由於 API 選擇響應格式,是基於客戶端發起的請求,因此,當接收到來著瀏覽器的請求時,會預設以HTML格式來描述資料。這讓API能夠返回,可以網頁瀏覽(web-browsable)的HTML表現。

擁有網頁瀏覽(web-browsable)的API,實在是非常的有用,使得開發和使用API,變成非常便利。這也大大降低了使用壁壘,讓其它開發者,更加容易的檢視和使用,你的API。

如需瞭解更多,有關視覺化API的特性,以及如何定製,可以查閱專題:視覺化API(browsable api

下步做什麼?

教程第三部(tutorial part 3),我們開始用基於類的檢視,並看看通用檢視(generic views)如何替我們省去大量的程式碼。

如果你覺得這個翻譯非常有幫助,不妨小額贊助我一下,你的認可,是我的動力!