django rest framework之請(qǐng)求與響應(yīng)(詳解)
前言:在上一篇文章,已經(jīng)實(shí)現(xiàn)了訪問指定URL就返回了指定的數(shù)據(jù),這也體現(xiàn)了RESTful API的一個(gè)理念,每一個(gè)URL代表著一個(gè)資源。當(dāng)然我們還知道RESTful API的另一個(gè)特性就是,發(fā)送不同的請(qǐng)求動(dòng)作,會(huì)返還不同的響應(yīng),這篇文章就講一下django-rest-framework這個(gè)工具在這方面給我們帶來的便捷操作。
一、Request對(duì)象
平時(shí)我們?cè)趯慏jango的視圖函數(shù)的時(shí)候,都會(huì)帶上一個(gè)request參數(shù),這樣就能處理平時(shí)搭建網(wǎng)站時(shí),瀏覽器訪問網(wǎng)頁時(shí)發(fā)出的常規(guī)的HttpRequest。但是現(xiàn)在我們導(dǎo)入了django-rest-framework,它能夠?qū)equest進(jìn)行拓展,并且提供更靈活的請(qǐng)求解析。這個(gè)特性體現(xiàn)在哪呢?請(qǐng)看下面這個(gè)例子:
<SPAN style="FONT-SIZE: 13px">request.POST # Only handles <SPAN style="COLOR: #ff0000">form data</SPAN>. Only works for '<SPAN style="COLOR: #ff0000">POST</SPAN>' method. request.data # Handles <SPAN style="COLOR: #ff0000">arbitrary(任意的) data</SPAN>. Works for '<SPAN style="COLOR: #ff0000">POST', 'PUT' and 'PATCH</SPAN>' methods. </SPAN>
request.POST只能處理前端發(fā)起的POST請(qǐng)求,只能處理表單提交的數(shù)據(jù)。而request.data可以處理任意數(shù)據(jù),而不單單是前端提交的表單數(shù)據(jù),可用于post, put, patch請(qǐng)求。
二、Response對(duì)象
和request對(duì)象一樣,django-rest-framework也對(duì)其進(jìn)行了很實(shí)用的拓展,在我上一篇文章的snippets/views.py中,我們導(dǎo)入了JsonResponse用于返回json格式的響應(yīng),在視圖函數(shù)中是這樣的:
@csrf_exempt def snippet_list(request): """ because we want to be able to POST to this view from clients that won't have a CSRF token we need to mark the view as csrf_exempt List all code snippets, or create a new 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的時(shí)候就需要指明json格式,這樣顯得很不實(shí)用而且很單一,所以經(jīng)過拓展后的Reponse對(duì)象就很方便了,它會(huì)根據(jù)客戶端的請(qǐng)求頭部信息來確定正確的內(nèi)容類型以返回給客戶端。只需如下代碼:
<SPAN style="FONT-SIZE: 13px">return Response(data) # <SPAN style="COLOR: #ff0000">Renders to content type as requested by the client. </SPAN></SPAN>
三、狀態(tài)碼
我們知道發(fā)送http請(qǐng)求時(shí)會(huì)返回各種各樣的狀態(tài)嗎,但是都是簡單的數(shù)字,比如200、404等,這些純數(shù)字標(biāo)識(shí)符有時(shí)候可能不夠明確或者客戶端在使用的時(shí)候不清楚錯(cuò)誤信息甚至是沒注意看不到,所以django-rest-framework也對(duì)此進(jìn)行了優(yōu)化,狀態(tài)碼會(huì)是HTTP_400_BAD_REQUEST、HTTP_404_NOT_FOUND這種,極大的提高可讀性
四、包裝API視圖
REST框架提供了兩個(gè)可用于編寫API視圖的包裝器。
•@api_view裝飾器用于處理基于函數(shù)的視圖
•APIView類用在基于視圖的類上
這些包裝提供了一些功能,讓我們省去很多工作。比如說確保你在視圖中收到Request對(duì)象或在你的Response對(duì)象中添加上下文,這樣就能實(shí)現(xiàn)內(nèi)容通信。
另外裝飾器可以在接收到輸入錯(cuò)誤的request.data時(shí)拋出ParseError異常,或者在適當(dāng)?shù)臅r(shí)候返回405 Method Not Allowed狀態(tài)碼。
五、Pulling it all together(使用)
Okay, let's go ahead and start using these new components to write a few views.
We don't need our JSONResponse class in views.py any more, so go ahead and delete that. Once that's done we can start refactoring(重構(gòu)) our views slightly.
在views.py文件中我們不再需要我們的JSONResponse類,所以繼續(xù)刪除。一旦完成,我們可以開始細(xì)微地重構(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): """ List all code snippets, or create a new 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)
可以看出,經(jīng)過改進(jìn)的代碼已經(jīng)把上面所說的幾個(gè)django-rest-framework帶來的特性都應(yīng)用起來了,我們可以看出程序代碼量變少,并且能處理的情況更多了。 比如說,在原本的視圖函數(shù)snippet_detail中,處理'PUT'請(qǐng)求的時(shí)候,需要先解析前端發(fā)來的json格式的數(shù)據(jù)再進(jìn)一步處理:
<SPAN style="FONT-SIZE: 13px">data = JSONParser().parse(request) serializer = SnippetSerializer(snippet, data=data) </SPAN>
也就是說需要分成兩步實(shí)現(xiàn),而且這里有一個(gè)限制就是只能解析json格式的數(shù)據(jù)流。而改進(jìn)后的程序只需一行代碼:
<SPAN style="FONT-SIZE: 13px">serializer = SnippetSerializer(data=request.data) </SPAN>
request.data can handle incoming json requests, but it can also handle other formats. Similarly we're returning response objects with data, but allowing REST framework to render the response into the correct content type for us.
request.data就可以獲取到提交過來的數(shù)據(jù)了,并且可以處理各種數(shù)據(jù)和各種請(qǐng)求動(dòng)作,方便了開發(fā)。還有在return的時(shí)候也不需要指定json格式了,由原本的:
<SPAN style="FONT-SIZE: 13px">return JsonResponse(serializer.data, status=201) </SPAN>
改成了
<SPAN style="FONT-SIZE: 13px">return Response(serializer.data,status=status.HTTP_201_CREATED) </SPAN>
這也意味著返回給客戶端的可以是json或者h(yuǎn)tml等格式的內(nèi)容,返回HTML格式的內(nèi)容的話,會(huì)在瀏覽器返回經(jīng)過渲染的、更美觀的頁面。同時(shí)可以看出狀態(tài)碼也改進(jìn)成了django-rest-framework給我們帶來的可讀性更高的狀態(tài)標(biāo)識(shí)碼,以上這些措施都很大程度的提高了對(duì)客戶的友好度。
對(duì)于另一個(gè)視圖函數(shù)的修改也是同樣的原理,這里就不做同樣的講解了,代碼如下:
@api_view(['GET', 'PUT', 'DELETE']) def snippet_detail(request, pk): """ Retrieve, update or delete a code 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)
以上就是對(duì)原有的常規(guī)的Django視圖函數(shù)的改進(jìn)。
總結(jié)一下就是處理request提交過來的數(shù)據(jù)不需要一定是json格式的數(shù)據(jù),返回的響應(yīng)也不需要一定是json數(shù)據(jù),也可以是經(jīng)過渲染的HTML頁面。稍后就會(huì)示范使用。
六、向URL添加可選的格式后綴
既然上面已經(jīng)說了返回給客戶端的Response可是json或者是HTML等格式的內(nèi)容,那么用戶在使用的時(shí)候是如何指定返回哪種格式的內(nèi)容呢,那就是在URL的最后加上后綴。比如http://127.0.0.1:8000/snippets.json,這樣就是用戶自己指定了返回json格式的Response,而不是我們?cè)诤笈_(tái)指定返回固定的格式。
只需對(duì)我們的程序稍加改進(jìn)就可以了,在兩個(gè)視圖函數(shù)添加關(guān)鍵詞參數(shù)format:
def snippet_list(request, format=None):
and
def snippet_detail(request, pk, format=None):
Now update the urls.py file slightly, to append a set of format_suffix_patterns(格式后綴模式) in addition to the existing URLs.
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)
七、How's it looking?
Go ahead and test the API from the command line, as we did in tutorial part 1. Everything is working pretty similarly, although we've got some nicer error handling if we send invalid requests.
We can get a list of all of the snippets, as before.
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" } ]
We can control the format of the response that we get back, either by using the Accept header:
<SPAN style="FONT-SIZE: 13px">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</SPAN>
Or by appending a format suffix:
<SPAN style="FONT-SIZE: 13px">http http://127.0.0.1:8000/snippets.json # JSON suffix http http://127.0.0.1:8000/snippets.api # Browsable API suffix</SPAN>
Similarly, we can control the format of the request that we send, using the Content-Type header.
# POST using form data 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 using 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" }
If you add a --debug switch to the http requests above, you will be able to see the request type in request headers.
Now go and open the API in a web browser, by visiting http://127.0.0.1:8000/snippets/.
Browsability
Because the API chooses the content type of the response based on the client request, it will, by default, return an HTML-formatted representation of the resource when that resource is requested by a web browser. This allows for the API to return a fully web-browsable HTML representation.
Having a web-browsable API is a huge usability win, and makes developing and using your API much easier. It also dramatically lowers the barrier-to-entry for other developers wanting to inspect and work with your API.
See the browsable api topic for more information about the browsable API feature and how to customize it.
瀏覽功能(中文)
由于API根據(jù)客戶端請(qǐng)求選擇響應(yīng)的內(nèi)容類型,因此默認(rèn)情況下,當(dāng)Web瀏覽器請(qǐng)求資源時(shí),將返回HTML格式的資源表示形式。這允許API返回完全的可瀏覽網(wǎng)頁的HTML表示。
擁有一個(gè)可瀏覽網(wǎng)頁的API是一個(gè)巨大的可用性勝利,并且使開發(fā)和使用您的API更容易。它也大大降低了想要檢查和使用您的API的其他開發(fā)人員的入門障礙。
有關(guān)可瀏覽的API功能以及如何對(duì)其進(jìn)行定制的更多信息,請(qǐng)參閱可瀏覽的api主題。
以上這篇django rest framework之請(qǐng)求與響應(yīng)(詳解)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python matplotlib繪制實(shí)時(shí)數(shù)據(jù)動(dòng)畫
Matplotlib作為Python的2D繪圖庫,它以各種硬拷貝格式和跨平臺(tái)的交互式環(huán)境生成出版質(zhì)量級(jí)別的圖形。本文將利用Matplotlib庫繪制實(shí)時(shí)數(shù)據(jù)動(dòng)畫,感興趣的可以了解一下2022-03-03Python中的錯(cuò)誤和異常處理簡單操作示例【try-except用法】
這篇文章主要介紹了Python中的錯(cuò)誤和異常處理簡單操作,結(jié)合實(shí)例形式分析了Python中try except在錯(cuò)誤與異常處理中的用法,需要的朋友可以參考下2017-07-07Python如何保留float類型小數(shù)點(diǎn)后3位
這篇文章主要介紹了Python如何保留float類型小數(shù)點(diǎn)后3位,具有很好的參考價(jià)值,希望對(duì)的大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05Qt通過QGraphicsview實(shí)現(xiàn)簡單縮放及還原效果
本文主要介紹通過QGraphicsview實(shí)現(xiàn)簡單的縮放以及縮放后還原原始大小,通過scale可以對(duì)view進(jìn)行放大或縮小,具體內(nèi)容詳情跟隨小編一起看看吧2021-09-09python網(wǎng)絡(luò)爬蟲精解之pyquery的使用說明
PyQuery是一個(gè)類似于jQuery的解析網(wǎng)頁工具,使用lxml操作xml和html文檔,它的語法和jQuery很像。和XPATH,Beautiful Soup比起來,PyQuery更加靈活,提供增加節(jié)點(diǎn)的class信息,移除某個(gè)節(jié)點(diǎn),提取文本信息等功能2021-09-09Python中使用Selenium環(huán)境安裝的方法步驟
這篇文章主要介紹了Python中使用Selenium環(huán)境安裝的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02非常詳細(xì)的Django連接mysql數(shù)據(jù)庫步驟記錄
我的Mysql中已經(jīng)有了項(xiàng)目需要使用的相關(guān)數(shù)據(jù)庫,現(xiàn)在需要通過django來獲取Mysql里的數(shù)據(jù)并使用,下面這篇文章主要給大家介紹了關(guān)于非常詳細(xì)的Django連接mysql數(shù)據(jù)庫步驟,需要的朋友可以參考下2022-10-10