django rest framework 中的三種視圖寫(xiě)法

一、基本視圖類(lèi) (APIView/@api_view)

1、類(lèi)基礎(chǔ)視圖(APIView)

DRF不同于django常規(guī)的view類(lèi),他有如下幾點(diǎn)優(yōu)點(diǎn):
* 提供了更好用的request對(duì)象,不同于普通的django HttpRequest更好用。
* 封裝了Response對(duì)象,代替了原有的django HttpResponse,視圖將管理內(nèi)容協(xié)商并設(shè)置正確的渲染器的響應(yīng)。
* 任何APIException異常將會(huì)被捕捉,并做適當(dāng)?shù)捻憫?yīng)。
* 傳入的請(qǐng)求將身份驗(yàn)證和適當(dāng)?shù)臋?quán)限和節(jié)流檢查將之前運(yùn)行調(diào)度請(qǐng)求處理程序的方法。
一個(gè)小例子:

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authenication, permissions

class ListUser(APIView):
“””

展示系統(tǒng)中所有的用戶(hù)
* 需要令牌認(rèn)證。
* 只有admin用戶(hù)能夠訪問(wèn)這一個(gè)視圖

"""
authentication_classes = (authentication.TokenAuthentication,)  # 認(rèn)證策略屬性
permission_classes = (permissions.IsAdminUser,) # 權(quán)限策略屬性

def get(self, requeset, format=None):
"""
返回一個(gè)用戶(hù)列表
"""
usernames = [user.username for user in  User.objects.all()]
return Response(usernames)
1) API策略屬性

以下的API策略屬性應(yīng)用于APIView,控制視圖的策略:
renderer_classes: 渲染器類(lèi)
parser_classes: 解釋器類(lèi)
authentication_classes: 權(quán)限類(lèi)
throttle_classes:節(jié)流類(lèi)
permission_classes: 權(quán)限類(lèi)
content_negotiation_class: 內(nèi)容協(xié)商類(lèi)

2)API 策略方法

以下的策略方法用在API的策略,通常不用重寫(xiě)它:
get_renderers(self): 獲取渲染器方法
get_parsers(self): 獲取解釋器方法
get_authenticators(self): 或缺認(rèn)證方法
get_throttles(self): 獲取節(jié)流方法
get_permissions(self): 獲取權(quán)限方法
get_content_negotiator(self): 獲取內(nèi)容協(xié)商方法

3)API策略實(shí)施方法

下列方法之前被稱(chēng)為調(diào)度處理程序方法:
check_permissions(self, request): 檢查權(quán)限
check_throttles(self, request): 檢查節(jié)流
check_content_negotiation(self, request, force=False): 檢查內(nèi)容協(xié)商

4)調(diào)度方法

這些執(zhí)行任何操作,需要發(fā)生之前或之后調(diào)用處理程序方法等.
initial(self, request, *args, **kwargs): 執(zhí)行任何操作,需要發(fā)生在處理程序方法之前被調(diào)用。這個(gè)方法是用來(lái)執(zhí)行權(quán)限和節(jié)流,并執(zhí)行內(nèi)容協(xié)商。
handle_exception(self, exc):拋出的任何異常處理程序方法將被傳遞給這個(gè)方法,而返回響應(yīng)實(shí)例,或者re-raises異常。
initialize_request(self, request, *args, **kwargs):確保請(qǐng)求對(duì)象傳遞給處理程序方法是request的一個(gè)實(shí)例,而不是django的HttpRequest
finalize_response(self, request, response, *args, **kwargs):確保任何響應(yīng)處理程序方法返回的對(duì)象將被呈現(xiàn)到正確的內(nèi)容類(lèi)型

2、函數(shù)基礎(chǔ)視圖(@api_view())

DRF同樣提供了另外一種函數(shù)基礎(chǔ)視圖來(lái)裝飾django的普通視圖,我們同樣可以使用request來(lái)接受請(qǐng)求和response響應(yīng)。
一個(gè)小例子:

from rest_framework.decorators import api_view

@api_view
def hello_world(request):
return Response({“message”:”Hello world!”})
1)api_view()使用方法

這個(gè)視圖將使用默認(rèn)渲染器、解析器、身份驗(yàn)證設(shè)置中指定的類(lèi)等。通常默認(rèn)只有GET方法,其他請(qǐng)求方法會(huì)報(bào)405錯(cuò)誤,我們可以手動(dòng)添加方法為這
裝飾器指定request方法。像這樣:

@api_view([‘GET’, ‘POST’])
def hello_world(request):
if request.method  == ‘POST’:
return Response({“message”:”Got some data”, “data”: request.data})
return Response({“messsage”:”Hello world!”})
2)API策略裝飾器

DRF提供了很多附加的裝飾器,我們可以添加到@api_view()后面,例如要加入一個(gè)節(jié)流的裝飾器來(lái)確保特定用戶(hù)每天只能一次通過(guò)這個(gè)視圖,我
我們就要用到@throttle_classes裝飾器:

from rest_framework.decorators import api_view, throttle_classes
from rest_framework.throttling import UserRateThrottle

class OncePerDayUserThrottle(UserRateThrottle):
rate = “1/day”

@api_view([‘GET’])
@throttle_classes([OncePerDayUserThrottle])
def view(request):
return Response({“message”:”Hello for to day! see you tomorrow!”})

其他可用API的裝飾器:
@renderer_classes(…)
@parser_classes(…)
@authentication_classes(…)
@throttle_classes(…)
@permission_classes(…)

二、 通用視圖(Generic views)

基于類(lèi)視圖的主要好處之一是他們?cè)试S您編寫(xiě)可重用的行為.
REST框架提供的通用視圖允許您快速構(gòu)建API觀點(diǎn)緊密地映射到您的數(shù)據(jù)庫(kù)模型.
如果通用視圖不適合你的需要API,您可以使用常規(guī)APIView類(lèi),或重用mixin和基類(lèi)使用的通用視圖來(lái)組成自己的組可重用通用視圖。

1、通用視圖

同樣我們可以設(shè)置一些類(lèi)屬性在通用視圖內(nèi),也可以根據(jù)特殊要寫(xiě)重寫(xiě)它的內(nèi)部視圖方法。一個(gè)小例子:

from django.contrib.auth.models import User
from myapp.serializers import UserSerializer
from rest_framework import generics
from rest_framework.permissions import IsAdminUser

class UserList(generics.ListCreateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = (IsAdminUser,)

def list(self, request):
# Note the use of get_queryset() instead of self.queryset
queryset = self.get_queryset()
serializer = UserSerializer(queryset, many=True)
return Response(serializer.data)

在urls配置中,我們可以使用.as_views()來(lái)轉(zhuǎn)換成視圖函數(shù),當(dāng)然也可以配置一些屬性

url(r’^/users/’, ListCreateAPIView.as_view(queryset=User.objects.all(), serializer_class=UserSerializer), name=’user-list’)

2、GenericAPIView通用視圖API參考:

GenericAPIView繼承了DRF的APIView類(lèi),為list和detail視圖增加了一些一般需求行為方法(提供queryset)。

1)屬性

基本屬性:
queryset: 用于返回query對(duì)象集合,也可以使用get_queryset()方法。
serializer_class: 序列化器類(lèi),應(yīng)該用于輸入進(jìn)行驗(yàn)證和反序列化,并用于序列化輸出。通常情況下,你必須設(shè)置這個(gè)屬性,或重寫(xiě)get_serializer_class()方法。
lookup_field: 模型的字段應(yīng)該用于執(zhí)行對(duì)象查找個(gè)別的模型實(shí)例
lookup_url_kwarg:URL應(yīng)該用于對(duì)象查找關(guān)鍵字參數(shù)

分頁(yè)屬性:
pagination_class: 用于返回一個(gè)分頁(yè)列表視圖的分頁(yè)類(lèi),默認(rèn)與settings中設(shè)置的DEFAULT_PAGINATION_CLASS 值相同,
可以通過(guò)’rest_framework.pagination.PageNumberPagination’設(shè)置分頁(yè)數(shù)
過(guò)濾器屬性:
filter_backends: 過(guò)濾queryset的類(lèi)列表,和在settings中設(shè)置DEFAULT_FILTER_BACKENDS 一樣

2)方法

基本方法:
get_queryset(): 返回queryset。(詳情見(jiàn)官網(wǎng)http://www.django-rest-framework.org/api-guide/generic-views/
get_object():獲取某一個(gè)具體的model實(shí)例對(duì)象。
保存與刪除掛鉤方法:
以下方法是mixins類(lèi)提供,提供簡(jiǎn)單的對(duì)象保存和刪除的行為重寫(xiě):
perform_create(self, serializer): CreateModelMixin 當(dāng)要保存對(duì)象時(shí)候會(huì)被調(diào)用
perform_update(self, serializer):UpdateModelMixin 當(dāng)要更新對(duì)象時(shí)候會(huì)被調(diào)用
perform_destroy(self, instance): DestoryModelMixin 當(dāng)藥刪除對(duì)象時(shí)候會(huì)被調(diào)用

3)、Mixins

mixin類(lèi)提供用于提供基礎(chǔ)視圖的操作行為。注意,mixin類(lèi)提供操作方法而不是定義處理程序方法,比如. get()和. post(),直接。這允許更靈活的組合的行為。
通過(guò)rest_framework.mixins引用。
ListModelMixin:提供list方法,列出queryset
CreateModelMixin: 提供create方法,創(chuàng)建和保存一個(gè)Model對(duì)象
RetrieveModelMixin:提供retrieve方法,檢索一個(gè)存在的model對(duì)象
UpdateModelMixin: 提供Update方法,更改一個(gè)模型對(duì)象
DestroyModelMixin:提供destroy方法,刪除一個(gè)模型對(duì)象

4)Generic

Generic通用視圖類(lèi)提供具體操作的通用視圖類(lèi),可以理解為Generic.GenericAPIView和mixin類(lèi)的合體,通過(guò)rest_framework.generic.調(diào)用

.CreateAPIView:

創(chuàng)建一個(gè)模型實(shí)例
提供post方法的處理器
繼承于:GenericAPIView,CreateModelMixin

.ListAPIView:

模型實(shí)例的集合
提供get方法處理器
繼承于:GenericAPIView,ListModelMixin

.RetrieveAPIView:

一個(gè)模型實(shí)例
提供get方法處理器
繼承于:GenericAPIView,RetrieveModelMixin

.DestoryAPIView:

刪除一個(gè)模型實(shí)例
提供delete方法處理器
繼承于:GenericAPIView,DestroyModelMixin

.UpdateAPIView:

修改模型實(shí)例,
提供put和patch方法處理器
繼承于:GenericAPIView,UpdateModelMixin

.ListCreateAPIView:

創(chuàng)建和展示一個(gè)模型實(shí)例集合
提供get和post處理器
繼承于:GenericAPIView,ListModelMixin,CreateModelMixin

.RetrieveUpdateAPIView:

讀和改一個(gè)模型實(shí)例
提供get,put,patch處理器
繼承于:GenericAPIView,RetrieveModelMixin,UpdateModelMixin

.RetrieveDestoryAPIView:

讀和刪除一個(gè)模型實(shí)例
提供get和delete處理器
繼承于:GenericAPIView,RetrieveModelMixin,DestroyModelMixin

.RetrieveUpdateDestroyAPIView:

讀、改和刪一個(gè)模型實(shí)例
get, put, patch,delete處理器
繼承于:GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin

三、視圖集合ViewSets

Django REST框架允許您將一組相關(guān)的邏輯視圖在一個(gè)類(lèi),ViewSet類(lèi)是一個(gè)簡(jiǎn)單類(lèi)型的基于類(lèi)的觀點(diǎn),沒(méi)有提供任何方法處理程序如.get()或. post(),
而代替提供方法比如.list()和create()。
一個(gè)小例子:

from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from myapps.serializers import UserSerializer
from rest_framework import viewsets
from rest_framework.response import Response

class UserViewSet(viewsets.ViewSet):
“””
A simple ViewSet for listing or retrieving users.
“””
def list(self, request):
queryset = User.objects.all()
serializer = UserSerializer(queryset, many=True)
return Response(serializer.data)

def retrieve(self, request, pk=None):
queryset = User.objects.all()
user = get_object_or_404(queryset, pk=pk)
serializer = UserSerializer(user)
return Response(serializer.data)

1).關(guān)于ViewSets

如果我們需要,我們需要為兩個(gè)GET請(qǐng)求分開(kāi)綁定視圖:
user_list = UserViewSet.as_view({“GET”:’list’})
user_detail = UserViewSet.as_view({‘GET’:’retrieve’})

但是通常我們不會(huì)這樣做,而是通過(guò)注冊(cè)路由來(lái)配置url:

from myapp.views import UserViewSet
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r’users’, UserViewSet)
urlpatterns = router.urls

或許你會(huì)經(jīng)常用到自己模型數(shù)據(jù),而不是手動(dòng)寫(xiě)視圖集合,這樣就要用到模型視圖集合ModelViewSet:

class UserViewSet(viewsets.ModelViewSet):
“””
A viewset for viewing and editing user instance
“””
serializer_class = UserSerializer
queryset = User.objects.all()

其他路由函數(shù)方法:

class UserViewSet(viewsets.ViewSet):
“””
Example empty viewset demonstrating the standard
actions that will be handled by a router class.

If you’re using format suffixes, make sure to also include
the format=None keyword argument for each action.
“””

def list(self, request):
pass

def create(self, request):
pass

def retrieve(self, request, pk=None):
pass

def update(self, request, pk=None):
pass

def partial_update(self, request, pk=None):
pass

def destroy(self, request, pk=None):
pass
如果你有特別的需要被路由到的方法,可以將它們標(biāo)記為需要路由使用@detail_route或@list_route修飾符。
@detail_route(methods=[‘post’], permission_classes=[IsAdminOrIsSelf])
def set_password(self, request, pk=None):
…
可以通過(guò)訪問(wèn)^users/{pk}/set_password/$來(lái)訪問(wèn)改視圖

2)ViewSets的API參考

.ViewSet:

繼承了APIView,你可以使用一些標(biāo)準(zhǔn)的屬性例如permission_class,authentication_classes去對(duì)視圖做一些策略。ViewSet同樣不提供具體
行為方法的實(shí)現(xiàn),你可以重寫(xiě)和定義一些請(qǐng)求處理方法。而代替了原來(lái)APIVIew的POST,GET等方法,取而代之的是list,create等方法。

.GenericViewSet:

繼承了GenericAPIView,提供了默認(rèn)的get_queryset()和get_object()等方法來(lái)獲取model數(shù)據(jù),但不提供任何請(qǐng)求處理方法。

.ModelViewSet:

繼承了GenericAPIView,增加了一些請(qǐng)求處理方法,如list(), retrieve(),create()等。

例子:

class AccountViewSet(viewsets.ModelViewSet):
“””
A simple ViewSet for viewing and editing accounts
“””
queryset = Account.objects.all()
serializer_class = AccountSerializer
permissions_classes = [IsAccountAdminOrReadOnly]
.ReadOnlyModelViewSet:

繼承了GenericAPIView,只增加了只讀的請(qǐng)求處理方法list()和retrieve()

自定義View類(lèi):

只需要繼承GenericAPIView, 增加mixins的相關(guān)處理方法。如:

class CreatListRetrieveViewSet(mixins.CreateModelMixin,
mixins.ListModelMixin,
mixins.RetrieveModelMixin,
View.GenericViewSet):
pass
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評(píng)論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,634評(píng)論 3 419
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事?!?“怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 176,653評(píng)論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 63,063評(píng)論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,835評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 55,235評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評(píng)論 3 442
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,459評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,000評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,819評(píng)論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,004評(píng)論 1 370
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,257評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,676評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,937評(píng)論 1 288
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,717評(píng)論 3 393
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,003評(píng)論 2 374