天天看點

DRF向導之請求和響應

src

從本節我們開始真正接觸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。

3. Status Codes

​ 在views當中使用數字化的HTTP狀态碼,會使你的代碼不宜閱讀,且不容易發現代碼中的錯誤。rest framework為每個狀态碼提供了更明确的辨別。例如

HTTP_400_BAD_REQUEST

status

module。相比于使用數字,在整個views中使用這類辨別符将更好。

4. 封裝API views

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

  1. @api_viwe

    decorator 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]主題。