step1:創(chuàng)建模型
step2:創(chuàng)建一個Serializer類
? ? ? ? 開始使用Web API的第一件事是提供一種將代碼片段實例序列化和反序列化為表示形式(如json)的方法。?
? ??????使用ModelSerializers:與Django提供的Form類和ModelForm類一樣,REST框架包括Serializer類和ModelSerializer類

? ? ? ? ModelSerializer類不會做任何特別神奇的事情,它們只是創(chuàng)建序列化器類的快捷方式:
? ? ? ? ? ? 1、一組自動確定的字段。
? ? ? ? ????2、create()和update()方法的簡單的實現(xiàn)。
請求和響應
????????1、請求對象
????????REST框架引入了Request擴展常規(guī)的對象HttpRequest,并提供更靈活的請求解析。Request對象的核心功能是request.data屬性,這與request.POST使用Web API?相似但更有用。
? ??????request.POST??#?Only?handles?form?data.??Only?works?for?'POST'?method.
????????request.data??#?Handles?arbitrary?data.??Works?for?'POST',?'PUT'?and?'PATCH'?methods.
????????2、響應對象
????????REST框架還引入了一個Response對象,它是一種類型的對象,它TemplateResponse采用未呈現(xiàn)的內(nèi)容,并使用內(nèi)容協(xié)商來確定正確的內(nèi)容類型以返回給客戶端。
????????return?Response(data)??#?Renders?to?content?type?as?requested?by?the?client.
????????3、狀態(tài)碼
? ? ? ? REST框架為每一個狀態(tài)碼更明確的標識符,如HTTP_400_BAD_REQUEST所述的status模塊。相對于使用數(shù)字標識符更好。
????????4、包裝API視圖
????????REST框架提供了兩個可用于編寫API視圖的包裝器。
? ? ? ? (1)@api_view用于使用基于功能的視圖的裝飾器。
? ? ? ? (2)繼承APIView的基于類的視圖工作。
????????這些包裝器提供了一些功能,例如確保您Request在視圖中接收實例,并將上下文添加到Response對象,以便可以執(zhí)行內(nèi)容協(xié)商。
????????包裝器還提供405 Method Not Allowed適當?shù)姆祷仨憫刃袨椋约疤幚硎褂酶袷讲徽_的輸入ParseError訪問時發(fā)生的任何異常request.data。
step3、視圖
(1)基于函數(shù)的視圖


????????我們不再明確地將我們的請求或響應明確綁定到給定的內(nèi)容類型。?request.data可以處理傳入的json請求,但它也可以處理其他格式。類似地,我們使用數(shù)據(jù)返回響應對象,但允許REST框架將響應呈現(xiàn)給正確的內(nèi)容類型。
向我們的網(wǎng)址添加可選的格式后綴
????????為了使我們的響應不再限于單一的內(nèi)容類型,我們可以為API端點添加對格式后綴的支持。使用格式后綴給我們明確指定給定格式的URL,這意味著我們的API將能夠處理諸如http://example.com/api/items/4.json之類的?URL?。
? ? ? ? (1)、首先format在兩個視圖中添加一個關(guān)鍵字參數(shù),就像這樣。

? ? ? ? (2)、在urls.py稍稍更新文件,format_suffix_patterns除了現(xiàn)有的URL之外還附加一組。

(2)基于類的視圖



(3)使用mixin來實現(xiàn)視圖
????????到目前為止,我們使用的創(chuàng)建/檢索/更新/刪除操作對于我們創(chuàng)建的任何模型支持的API視圖將非常相似。 這些常見的行為是在REST框架的mixin類中實現(xiàn)的。

???????用GenericAPIView創(chuàng)建一個視圖,并添加ListModelMixin和CreateModelMixin,到目前為止足夠簡單?;愄峁┖诵墓δ?,mixin類提供.list()和.create()操作。我們明確的將get和post方法綁定到適當?shù)牟僮?/b>上。

????????我們再次使用GenericAPIView類來提供核心功能,并在mixin中添加.retrieve(),.update()和.destroy()方法。
(4)使用通用的基于類的視圖

step4、權(quán)限驗證
????????目前,我們的API對誰可以編輯或刪除代碼段沒有任何限制。我們想要一些更高級的行為:
????????代碼段始終與創(chuàng)建者相關(guān)聯(lián)。
????????只有身份驗證的用戶可以創(chuàng)建片段。
????????只有片段的創(chuàng)建者可以更新或刪除它。
????????未經(jīng)身份驗證的請求應具有完全只讀訪問權(quán)限。
? ??????1、將用戶信息添加到我們的模型
????????我們將對我們的Snippet模型類進行一些更改。首先,我們添加幾個字段。其中一個字段將用于表示創(chuàng)建代碼段的用戶。另一個字段將用于存儲代碼的突出顯示的HTML表示。

? ??????2、為用戶模型添加端點
????????現(xiàn)在我們有一些用戶可以使用,我們最好將這些用戶的表示添加到我們的API中。創(chuàng)建一個新的serializer很容易。在serializers.py添加:

????????因為在User模型上'snippets'是一個反向關(guān)系,所以在使用ModelSerializer該類時它不會被默認包含,所以我們需要為它添加一個顯式字段。
? ??3、將片段與用戶關(guān)聯(lián)
????????現(xiàn)在,如果我們創(chuàng)建了一個代碼片段,那么將無法將創(chuàng)建該代碼段的用戶與代碼段實例相關(guān)聯(lián)。用戶不是作為序列化表示的一部分發(fā)送的,而是傳入請求的屬性。
????????我們處理的方式是覆蓋.perform_create()我們的代碼片段視圖上的方法,這樣我們可以修改實例保存的管理方式,并處理傳入請求或請求的URL中隱含的任何信息。
????????在SnippetList視圖類中,添加以下方法:

4、更新serializer
????????現(xiàn)在,這些片段與創(chuàng)建它們的用戶相關(guān)聯(lián),我們更新我們SnippetSerializer來反映這一點。將以下字段添加到序列化器定義中serializers.py:

? ??????確保您還添加'owner',到內(nèi)部Meta類的字段列表。
????????這個領(lǐng)域正在做一些很有趣的事情。source的那個屬性參數(shù)控制用于填充的字段,并且可以在對串行化實例的任何屬性點。它也可以采用上面顯示的點劃線,在這種情況下,它將以與Django模板語言一起使用的相似方式遍歷給定的屬性。
????????我們添加了字段是類型化ReadOnlyField類,相對于其他類型的字段,如CharField,BooleanField等...類型化ReadOnlyField始終是只讀的,并且將用于序列化表示形式,但不會被用于更新模型他們被反序列化的實例。我們也可以CharField(read_only=True)在這里使用。
5、添加視圖所需的權(quán)限
????????現(xiàn)在,代碼片段與用戶相關(guān)聯(lián),我們希望確保只有經(jīng)過身份驗證的用戶才能創(chuàng)建,更新和刪除代碼段。
????????REST框架包括許多權(quán)限類,我們可以使用它們來限制誰可以訪問給定的視圖。在這種情況下,我們正在尋找的是IsAuthenticatedOrReadOnly,這將確保經(jīng)過身份驗證的請求獲得讀寫訪問權(quán)限,未經(jīng)身份驗證的請求將獲得只讀訪問權(quán)限。

????????如果您打開瀏覽器并導航到目前可瀏覽的API,那么您將發(fā)現(xiàn)無法再創(chuàng)建新的代碼段。為了做到這一點,我們需要能夠以用戶身份登錄。
????????我們可以通過編輯項目級urls.py文件中的URLconf來添加可瀏覽API使用的登錄視圖。

????????r'^api-auth/'模式的一部分實際上可以是您要使用的任何URL。唯一的限制是所包含的URL必須使用'rest_framework'命名空間。
7、對象級權(quán)限
????????我們希望所有的代碼片段都可以被任何人看到,但也要確保只有創(chuàng)建代碼段的用戶才能更新或刪除它。要做到這一點,我們將需要創(chuàng)建一個自定義權(quán)限。
????????在片段應用中,創(chuàng)建一個新文件,permissions.py

????????現(xiàn)在,我們可以通過編輯視圖類中的permission_classes屬性將該自定義權(quán)限添加到我們的代碼段實例端點SnippetDetail:

????????現(xiàn)在,如果再次打開瀏覽器,您會發(fā)現(xiàn)如果您以與創(chuàng)建代碼段相同的用戶身份登錄,“DELETE”和“PUT”操作只會顯示在代碼段實例端點上。
8、使用API進行身份驗證
????????因為我們現(xiàn)在有一組API的權(quán)限,如果我們要編輯任何片段,我們需要驗證我們的請求。我們還沒有設(shè)置任何身份驗證類,所以默認值現(xiàn)在被應用,哪些是SessionAuthentication和BasicAuthentication。
????????當我們通過Web瀏覽器與API進行交互時,我們可以登錄,然后瀏覽器會話將為請求提供所需的身份驗證。
????????如果我們以編程方式與API交互,我們需要在每個請求上顯式提供身份驗證憑據(jù)。
????????如果我們嘗試創(chuàng)建一個沒有驗證的代碼段,我們會收到一個錯誤:

step5、ViewSets&Routers
????????REST框架包括一個處理的抽象ViewSets,它允許開發(fā)人員集中精力對API的狀態(tài)和交互進行建模,并根據(jù)常規(guī)約定使URL構(gòu)造自動處理。
????????ViewSet類是幾乎同樣的事情View類,但他們提供諸如操作read,或者update,而不是方法處理,如get或put。
????????一個ViewSet類在最后一刻被綁定到一組方法處理程序,當它被實例化成一組視圖時,通常通過使用一個Router類來處理為你定義URL conf的復雜性。
1、我們來看一下我們目前的view,并把它們重構(gòu)成視圖集。
????????首先,讓我們來重構(gòu)我們UserList和UserDetail View納入一個單一的UserViewSet。我們可以刪除這兩個視圖,并將其替換為單個類:

????????在這里,我們使用ReadOnlyModelViewSet該類來自動提供默認的“只讀”操作。我們?nèi)匀徽缥覀兪褂贸R?guī)視圖一樣設(shè)置queryset和serializer_class屬性,但是我們不再需要向兩個不同的類提供相同的信息。
????????接下來我們要更換SnippetList,SnippetDetail和SnippetHighlight視圖類。我們可以刪除三個視圖,并再次替換為單個類。

????????這一次,我們已經(jīng)使用了ModelViewSet類來獲取完整的默認讀寫操作。
????????請注意,我們還使用@detail_route裝飾器創(chuàng)建一個名為的自定義操作highlight。此裝飾器可用于添加不適合標準create/update/delete樣式的任何自定義端點。
????????默認情況下,使用@detail_route裝飾器的自定義操作將響應GET請求。methods如果我們想要一個響應POST請求的動作,我們可以使用該參數(shù)。
????????默認情況下,自定義操作的URL取決于方法名稱本身。如果要更改url應該構(gòu)造的方式,可以將url_path作為decorator的關(guān)鍵字參數(shù)。
2、明確地將ViewSets綁定到URL
????????當我們定義URLConf時,處理程序方法只會被綁定到動作上。看看發(fā)生什么事情,讓我們首先從ViewSets中明確創(chuàng)建一組視圖。
????????在urls.py文件中,我們將我們的ViewSet類綁定到一組具體的視圖中。

????????請注意,我們?nèi)绾蜼iewSet通過將http方法綁定到每個視圖所需的操作,從每個類創(chuàng)建多個視圖。
????????現(xiàn)在我們將資源綁定到具體的視圖中,我們可以像往常一樣使用URL conf注冊視圖。

3.使用路由器
????????因為我們使用ViewSet類而不是View類,我們實際上不需要設(shè)計自己的URL。將資源連接到視圖和網(wǎng)址的約定可以使用Router類自動處理。我們需要做的就是使用路由器注冊相應的視圖集,然后讓它執(zhí)行其余操作。
????????這是我們的重新連線的urls.py文件。

????????與路由器注冊視圖與提供urlpattern類似。我們包括兩個參數(shù):視圖的URL前綴和視圖本身。
DefaultRouter我們使用的類也會自動為我們創(chuàng)建API根視圖,因此我們現(xiàn)在可以api_root從我們的views模塊中刪除該方法。