Django編寫RESTful API(二):請求和響應

歡迎訪問個人我的網站:www.comingnext.cnhtml

 

 

前言

在上一篇文章,已經實現了訪問指定URL就返回了指定的數據,這也體現了RESTful API的一個理念,每個URL表明着一個資源。固然咱們還知道RESTful API的另外一個特性就是,發送不一樣的請求動做,會返還不一樣的響應,這篇文章就講一下django-rest-framework這個工具在這方面給咱們帶來的便捷操做。django


Request對象

平時咱們在寫Django的視圖函數的時候,都會帶上一個request參數,這樣就能處理平時搭建網站時,瀏覽器訪問網頁時發出的常規的HttpRequest。可是如今咱們導入了django-rest-framework,它可以對request進行拓展,而且提供更靈活的請求解析。這個特性體如今哪呢?請看下面這個例子:json

request.POST  # 只能處理表單數據.只能處理POST請求
request.data  # 能處理各類數據。  能夠處理'POST', 'PUT' 和 'PATCH'模式的請求

 

這個例子裏面的註釋已經說得很清楚,拓展後的request使用request.data就能夠處理各類各樣的請求了,而本來的request在處理時須要指定請求模式。api


Response對象

和request對象同樣,django-rest-framework也對其進行了很實用的拓展,在我上一篇文章的snippets/views.py中,咱們導入了JsonResponse用於返回json格式的響應,在視圖函數中是這樣的:瀏覽器

@csrf_exempt
def snippet_list(request):
    """
    列出全部已經存在的snippet或者建立一個新的snippet
    """
    if request.method == 'GET':
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return JsonResponse(serializer.data, safe=False)

    elif request.method == 'POST':
        data = JSONParser().parse(request)
        serializer = SnippetSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        return JsonResponse(serializer.errors, status=400)

 

也就是說,在return的時候就須要指明json格式,這樣顯得很不實用並且很單一,因此通過拓展後的Reponse對象就很方便了,它會根據客戶端的請求頭部信息來肯定正確的內容類型以返回給客戶端。只需以下代碼:restful

return Response(data) 


稍後會改進上一篇文章的程序對此進一步的具體講解。app


狀態碼

咱們知道發送http請求時會返回各類各樣的狀態嗎,可是都是簡單的數字,好比200、404等,這些純數字標識符有時候可能不夠明確或者客戶端在使用的時候不清楚錯誤信息甚至是沒注意看不到,因此django-rest-framework也對此進行了優化,狀態碼會是HTTP_400_BAD_REQUEST、HTTP_404_NOT_FOUND這種,極大的提升可讀性。框架


裝飾API視圖

REST框架還提供了一個裝飾器和一個類來包裝視圖函數,可使用它們來寫API視圖,讓程序能處理的狀況更多。函數

  1. @api_view裝飾器用在基於視圖的方法上。
  2. APIView類用在基於視圖的類上。

注意:本文使用的是基於視圖方法,因此使用的是裝飾器@api_view,APIview這個類暫時不會說起。工具

這兩個東西提供的一些功能,讓咱們省去不少工做,好比說確保你在視圖中收到Request對象或在你的Response對象中添加上下文,這樣就能實現內容通訊。

另外裝飾器能夠在接收到輸入錯誤的request.data時拋出ParseError異常,或者在適當的時候返回405 Method Not Allowed狀態碼。


把這些都使用起來

上面說了這麼多拓展和優化,接下來就把它們都使用起來,改進一下本來的snippets/views.py,程序以下:

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):
    """
    列出全部已經存在的snippet或者建立一個新的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)

 

能夠看出,通過改進的代碼已經把上面所說的幾個django-rest-framework帶來的特性都應用起來了,咱們能夠看出程序代碼量變少,而且能處理的狀況更多了。 好比說,在本來的視圖函數snippet_detail中,處理'PUT'請求的時候,須要先解析json格式的數據再進一步處理:

data = JSONParser().parse(request)
serializer = SnippetSerializer(snippet, data=data)

 

也就是說須要分紅兩步實現,並且這裏有一個限制就是隻能解析json格式的數據流。而改進後的程序只需一行代碼:

serializer = SnippetSerializer(data=request.data)

 

直接使用以前說的request.data就能夠獲取到提交過來的數據了,而且能夠處理各類數據和各類請求動做,方便了開發。

還有在return的時候也不須要指定json格式了,由本來的

return JsonResponse(serializer.data, status=201)

改爲了

return Response(serializer.data,status=status.HTTP_201_CREATED)

 

這也意味着返回給客戶端的能夠是json或者html等格式的內容,返回HTML格式的內容的話,會在瀏覽器返回通過渲染的、更美觀的頁面。同時能夠看出狀態碼也改進成了django-rest-framework給咱們帶來的可讀性更高的狀態標識碼,以上這些措施都很大程度的提升了對客戶的友好度。

對於另外一個視圖函數的修改也是一樣的原理,這裏就不作一樣的講解了,代碼以下:

@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)
        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提交過來的數據不須要必定是json格式的數據,返回的響應也不須要必定是json數據,也能夠是通過渲染的HTML頁面。稍後就會示範使用。


向URL添加可選的格式後綴

既然上面已經說了返回給客戶端的Response但是json或者是HTML等格式的內容,那麼用戶在使用的時候是如何指定返回哪一種格式的內容呢,那就是在URL的最後加上後綴。好比http://127.0.0.1:8000/snippets.json,這樣就是用戶本身指定了返回json格式的Response,而不是咱們在後臺指定返回固定的格式。

只需對咱們的程序稍加改進就能夠了,在兩個視圖函數添加關鍵詞參數format:

def snippet_list(request, format=None):

以及

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

 

再修改一下snippets/urls.py,導入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)

 


改進後的使用

首先固然仍是能夠像上一篇文章中那樣的使用:

image

也能夠經過設置Accept頭部信息來控制返回的格式:

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

 

效果以下(返回的是頁面的HTML代碼,只展現了一部分):

 image

還能夠直接加格式後綴:

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

 

固然啦,在命令行查看HTML代碼就沒啥意思了,咱們能夠直接在瀏覽器輸入 http://127.0.0.1:8000/snippets.api 進行查看,會獲得一個美觀的頁面:

image

若是咱們要增添數據怎麼辦?咱們能夠控制 Content-Type 頭部信息來提交POST請求:

http --form POST http://127.0.0.1:8000/snippets/ code="print 123"
http --json POST http://127.0.0.1:8000/snippets/ code="print 456"

 

它會自動在原有的數據後面添加你提交過去的數據,效果以下:

image

上面說了,改進後能夠處理錯誤的提交,好比把code改爲了codes,就會給出錯誤信息:

image

圖中給出的錯誤信息是 400 Bad Request,這和咱們在視圖函數中定義的是同樣的:

return Response(serializer.data,status=status.HTTP_400_BAD_REQUEST)

 

在請求中若是加入了--debug能夠查看到詳細的請求信息和類型:

image

在上面介紹@api_view和APIView的時候,提到了在適當的時候返回405 Method Not Allowed狀態碼。這個所謂適當的時候就要回看到剛纔寫視圖函數的時候,修飾器的代碼:

@api_view(['GET','POST'])

以及

@api_view(['GET','PUT','DELETE'])

這兩行代碼就規定了在調用這兩個函數,也就是訪問到相關的URL時,只能使用指定的請求動做,不然就會報出405 Method Not Allowed錯誤。例如訪問 http://127.0.0.1:8000/snippets.json 時用了PUT請求就會報這個錯:

image

正確的更改數據應該以下:

http --json PUT http://127.0.0.1:8000/snippets/1.json code="hello world"

 

image

這樣就把 id=1 的數據修改了。想要刪除也是同樣的:

image

這樣就能夠把 id=3 的數據刪除掉了。


OK,關於Django RESTful API的請求和響應部分的處理就先講到這了。下一篇會介紹基於類的視圖,多謝支持~

本文地址:http://www.cnblogs.com/zivwong/p/7427394.html
做者博客:ziv歡迎轉載,請在明顯位置給出出處及連接

相關文章
相關標籤/搜索