Django drf 請求和響應(yīng)

2020-01-22 11:22 更新

從現(xiàn)在開始,我們將真正開始接觸REST框架的核心。 我們來介紹幾個基本的構(gòu)建模塊。

請求對象(Request objects)

REST框架引入了一個擴展了常規(guī)HttpRequest的Request對象,并提供了更靈活的請求解析。Request對象的核心功能是request.data屬性,它與request.POST類似,但對于使用Web API更為有用。

request.POST  # 只處理表單數(shù)據(jù)  只適用于'POST'方法
request.data  # 處理任意數(shù)據(jù)  適用于'POST','PUT'和'PATCH'方法

響應(yīng)對象(Response objects)

REST框架還引入了一個Response對象,這是一種獲取未渲染(unrendered)內(nèi)容的TemplateResponse類型,并使用內(nèi)容協(xié)商來確定返回給客戶端的正確內(nèi)容類型。

return Response(data)  # 渲染成客戶端請求的內(nèi)容類型。

狀態(tài)碼(Status codes)

在你的視圖(views)中使用純數(shù)字的HTTP 狀態(tài)碼并不總是那么容易被理解。而且如果錯誤代碼出錯,很容易被忽略。REST框架為status模塊中的每個狀態(tài)代碼(如HTTP_400_BAD_REQUEST)提供更明確的標識符。使用它們來代替純數(shù)字的HTTP狀態(tài)碼是個很好的主意。

包裝(wrapping)API視圖

REST框架提供了兩個可用于編寫API視圖的包裝器(wrappers)。

  1. 用于基于函數(shù)視圖的@api_view裝飾器。
  2. 用于基于類視圖的APIView類。

這些包裝器提供了一些功能,例如確保你在視圖中接收到Request實例,并將上下文添加到Response,以便可以執(zhí)行內(nèi)容協(xié)商。

包裝器還提供了諸如在適當(dāng)時候返回405 Method Not Allowed響應(yīng),并處理在使用格式錯誤的輸入來訪問request.data時發(fā)生的任何ParseError異常。

組合在一起

好的,我們開始使用這些新的組件來寫幾個視圖。

我們在views.py中不再需要JSONResponse類了,所以把它刪除掉。刪除之后,我們就可以開始重構(gòu)我們的視圖了。

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,或者創(chuàng)建一個新的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)

我們的實例視圖比前面的示例有所改進。它稍微簡潔一點,現(xiàn)在的代碼與我們使用Forms API時非常相似。我們還使用了命名狀態(tài)代碼,這使得響應(yīng)意義更加明顯。

以下是views.py模塊中單個snippet的視圖。

@api_view(['GET', 'PUT', 'DELETE'])
def snippet_detail(request, pk):
    """
    獲取,更新或刪除一個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)

這對我們來說應(yīng)該都是非常熟悉的,-它和正常Django視圖并沒有什么不同。

注意,我們不再顯式地將請求或響應(yīng)綁定到給定的內(nèi)容類型。request.data可以處理傳入的json請求,但它也可以處理其他格式。同樣,我們返回帶有數(shù)據(jù)的響應(yīng)對象,但允許REST框架將響應(yīng)給我們渲染成正確的內(nèi)容類型。

給我們的網(wǎng)址添加可選的格式后綴

為了充分利用我們的響應(yīng)不再與單一內(nèi)容類型連接,我們可以為API路徑添加對格式后綴的支持。使用格式后綴給我們明確指定了給定格式的URL,這意味著我們的API將能夠處理諸如http://example.com/api/items/4.json之類的URL。

像下面這樣在這兩個視圖中添加一個format關(guān)鍵字參數(shù)。

def snippet_list(request, format=None):

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

現(xiàn)在更新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)

我們不一定需要添加這些額外的url模式,但它給了我們一個簡單,清晰的方式來引用特定的格式。

怎么查看結(jié)果?

從命令行開始測試API,就像我們在教程第一部分中所做的那樣。一切操作都很相似,盡管我們發(fā)送無效的請求也會有一些更好的錯誤處理了。

我們可以像以前一樣獲取所有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"
  }
]

我們可以通過使用Accept標頭來控制我們回復(fù)的響應(yīng)格式:

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

或者通過附加格式后綴:

http http://127.0.0.1:8000/snippets.json  # JSON后綴
http http://127.0.0.1:8000/snippets.api   # 瀏覽器可瀏覽API后綴

類似地,我們可以使用Content-Type頭控制我們發(fā)送的請求的格式。

# POST表單數(shù)據(jù)
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數(shù)據(jù)
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àn)在可以在瀏覽器中訪問http://127.0.0.1:8000/snippets/查看API。

瀏覽功能

由于API根據(jù)客戶端請求選擇響應(yīng)的內(nèi)容類型,因此默認情況下,當(dāng)Web瀏覽器請求該資源時,它將返回資源的HTML格式表示。這允許API返回完全瀏覽器可瀏覽(web-browsable)的HTML表示。

擁有支持瀏覽器可瀏覽的API在可用性方面完勝并使開發(fā)和使用你的API更容易。它也大大降低了其他開發(fā)人員要檢查和使用API??的障礙。


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號