DjangoRest framework-視圖類(lèi)API實(shí)現(xiàn)極簡(jiǎn)開(kāi)發(fā)

在完成序列化器serializers的配置過(guò)后放接,我們可以進(jìn)一步使用DjangoRest framework提供的強(qiáng)大視圖類(lèi)API簡(jiǎn)化視圖的開(kāi)發(fā)呼盆。

Request和Response

(一)Request

首先需要清楚的一點(diǎn)是柠衅,當(dāng)視圖函數(shù)繼承與DRF的View時(shí)成翩,傳入視圖內(nèi)的request對(duì)象就不再是Django默認(rèn)的HttpRequest對(duì)象了败去,而變成了DRF擴(kuò)展的Request類(lèi)對(duì)象暴构,該對(duì)象提供了更友好的數(shù)據(jù)接收方式:

1. request.data
request.data返回解析之后的請(qǐng)求體數(shù)據(jù),無(wú)需再使用data = json.loads(request.body.decode())的方法來(lái)獲取post及put等方法傳輸?shù)臄?shù)據(jù)置鼻。

  • 包含了解析之后的文件和非文件數(shù)據(jù)
  • 包含了對(duì)POST镇饮、PUT、PATCH請(qǐng)求方式解析后的數(shù)據(jù)
  • 利用了REST framework的parsers解析器箕母,不僅支持表單類(lèi)型數(shù)據(jù)储藐,也支持JSON數(shù)據(jù)

2. request.query_params
使用request.query_params獲取前端請(qǐng)求中傳遞的關(guān)鍵字參數(shù),與Django中的request.GET相同嘶是,但DRF的方法命名能更準(zhǔn)確的指明我們?cè)谧鍪裁础?/p>

(二) Response
與Django自帶的HttpResponse對(duì)象不同钙勃,DRF還提供了一個(gè)更為便捷的響應(yīng)類(lèi)
Response:rest_framework.response.Response
使用該類(lèi)構(gòu)件響應(yīng)對(duì)象時(shí)聂喇,不必再像之前那樣需先將數(shù)據(jù)進(jìn)行轉(zhuǎn)換辖源。
data數(shù)據(jù)不要是render處理之后的數(shù)據(jù),只需傳遞python的內(nèi)建類(lèi)型數(shù)據(jù)即可希太,REST framework會(huì)使用renderer渲染器處理data克饶。

  1. 響應(yīng)方式
    Response(data, status=None, template_name=None, headers=None, content_type=None)
  2. 參數(shù)說(shuō)明
參數(shù) 說(shuō)明
data 傳遞的序列化處理后的數(shù)據(jù)
status 狀態(tài)碼,默認(rèn)為200
template_name 模板名稱(chēng)誊辉,使用HTMLRenderer 時(shí)需指明
headers 用于存放響應(yīng)頭信息的字典
content_type 響應(yīng)數(shù)據(jù)的Content-Type矾湃,通常此參數(shù)無(wú)需傳遞,REST framework會(huì)根據(jù)前端所需類(lèi)型數(shù)據(jù)來(lái)設(shè)置該參數(shù)堕澄。
  1. 關(guān)于狀態(tài)碼
    DRF提供了狀態(tài)碼常量邀跃,導(dǎo)入rest_framework.status后使用,使用內(nèi)置狀態(tài)碼更加規(guī)范蛙紫。

DRF提供的視圖View類(lèi)

使用DRF提供的視圖類(lèi)時(shí)拍屑,我們不再繼承django自帶的django.views.View類(lèi),而是繼承來(lái)自DRF的VIEW

一. APIView

APIView是REST framework提供的所有視圖的基類(lèi)惊来,繼承自Django的View父類(lèi):rest_framework.views.APIView丽涩。

  1. APIView與View的不同之處在于:
  • 傳入到視圖方法中的是REST framework的Request對(duì)象棺滞,而不是Django的HttpRequeset對(duì)象裁蚁;
  • 視圖方法可以返回REST framework的Response對(duì)象,視圖會(huì)為響應(yīng)數(shù)據(jù)設(shè)置(render)符合前端要求的格式继准;
  • 任何APIException異常都會(huì)被捕獲到枉证,并且處理成合適的響應(yīng)信息;
  • 在進(jìn)行dispatch()分發(fā)前移必,會(huì)對(duì)請(qǐng)求進(jìn)行身份認(rèn)證室谚、權(quán)限檢查、流量控制。
  1. 繼承APIView的視圖類(lèi)代碼示例
from . models import BookInfo
from .serializers import  BookModelSerializer # 導(dǎo)入序列化器
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

class BooksAPIView(APIView):
    # 獲取所有書(shū)
    def get(self,request):
        books = BookInfo.objects.all()
        serializer = BookModelSerializer(books, many=True)
        print(serializer.data)
        return Response(serializer.data)
    # 新增一本書(shū)
    def post(self, request):
        data_dict = request.data
        serializer = BookModelSerializer(data=data_dict)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

二达箍、GenericAPIView

此類(lèi)擴(kuò)展了REST框架的APIView類(lèi):rest_framework.generics.GenericAPIView娇跟。
增加了對(duì)于列表視圖和詳情視圖可能用到的通用支持方法,通常使用時(shí)仅仆,可搭配一個(gè)或多個(gè)Mixin擴(kuò)展類(lèi)。

  1. 基本設(shè)置
    使用繼承于GenericAPIView的視圖類(lèi)時(shí)陈瘦,需要先定義基本類(lèi)屬性:
    (1) queryset :列表視圖的查詢集
    (2) serializer_class :視圖使用的序列化器
    以上兩個(gè)為必須設(shè)置的屬性
    (3)lookup_field:用于執(zhí)行單個(gè)模型實(shí)例的對(duì)象查找的模型字段,不設(shè)置時(shí)默認(rèn)為pk字段
    (4)lookup_url_kwarg:查詢單一數(shù)據(jù)時(shí)URL中的參數(shù)關(guān)鍵字名稱(chēng)潮售,默認(rèn)與look_field相同
    (5)pagination_class:分頁(yè)控制類(lèi)
    (6)filter_backends:用于過(guò)濾查詢集的過(guò)濾器后端類(lèi)列表

  2. 基本方法
    (1) get_queryset(self): 返回視圖使用的查詢集
    (2) get_serializer_class(self): 返回序列化器類(lèi)
    (3) get_object(self): 返回lookup_field設(shè)置指定的模型類(lèi)數(shù)據(jù)對(duì)象痊项。

3.繼承GenericAPIView視圖類(lèi)的代碼示例

from . models import BookInfo
from .serializers import BookModelSerializer
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response

class BooksAPIView(GenericAPIView):
    serializer_class = BookModelSerializer
    queryset = BookInfo.objects.all()
    # 獲取所有
    def get(self,request):
        books = self.get_queryset()
        serializer = self.get_serializer(books, many=True)
        return Response(serializer.data)
    # 新增一本書(shū)
    def post(self, request):
        data_dict = request.data
        serializer = self.get_serializer(data_dict)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

看起來(lái)代碼量并沒(méi)有減少,只是將序列化器的初始化酥诽、數(shù)據(jù)集的查詢提取了出來(lái)鞍泉。
但GenericAPIView類(lèi)主要是聯(lián)合它的Mixin類(lèi)一起使用的。

三肮帐、Mixin擴(kuò)展類(lèi)

from rest_framework.mixins import CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin,ListModelMixin
DRF總共提供了5個(gè)Mixin擴(kuò)展類(lèi)咖驮,他們只提供操作的方法,而需要同時(shí)繼承GenericAPIView類(lèi)训枢,并繼承對(duì)用功能的Mixin類(lèi):

Minx類(lèi) 作用 調(diào)用方式
ListModelMixin 實(shí)現(xiàn)查詢集功能(get) list
CreateModelMixin 實(shí)現(xiàn)創(chuàng)建和保存功能(post) create
RetrieveModelMixin 實(shí)現(xiàn)查詢指定單一數(shù)據(jù)功能(get) retrieve
UpdateModelMixin 實(shí)現(xiàn)更新功能(put) update
DestroyModelMixin 實(shí)現(xiàn)刪除功能(delete) destroy
  1. 使用代碼示例
    該視圖類(lèi)需要實(shí)現(xiàn)查詢所有書(shū)功能游沿、創(chuàng)建一本新書(shū)的功能,因此除繼承GenericAPIView外, 還需繼承ListModelMixin, CreateModelMixin類(lèi)肮砾。
from . models import BookInfo
from .serializers import BookModelSerializer
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import CreateModelMixin,UpdateModelMixin,DestroyModelMixin,RetrieveModelMixin,ListModelMixin

class BooksAPIView(GenericAPIView, ListModelMixin, CreateModelMixin):
    serializer_class = BookModelSerializer
    queryset = BookInfo.objects.all()
    # 獲取所有
    def get(self,request):
        return self.list(request)
    # 新增一本書(shū)
    def post(self, request):
        return self.create(request)

class BookAPIView(GenericAPIView,RetrieveModelMixin,UpdateModelMixin,DestroyModelMixin):
    serializer_class = BookModelSerializer
    queryset = BookInfo.objects.all()
    # 獲取指定id書(shū)
    def get(self,request, pk):
        return self.retrieve(request, pk)
    # 修改指定書(shū)信息
    def put(self, request, pk):
        return self.update(request, pk)
    # 刪除指定書(shū)
    def delete(self,request, pk):
        return self.delete(request,pk)

可以看到诀黍,使用Mixin擴(kuò)展類(lèi)后,代碼量大大縮減仗处,連邏輯代碼都被封裝起來(lái)了眯勾。

  1. mixin源碼示例

mixin類(lèi)在內(nèi)部定義了方法將:數(shù)據(jù)集的查詢及獲取、頁(yè)碼操作婆誓、序列化器的調(diào)用吃环、Response響應(yīng) 都封裝在了一起,我們需要做的就只是繼承然后調(diào)用該內(nèi)部方法即可ListModelMixin源碼示例:

class ListModelMixin(object):
    """
    List a queryset.
    """
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

其內(nèi)部相當(dāng)于將我們寫(xiě)的邏輯代碼部分都封裝起來(lái)了洋幻,因?yàn)槠溥壿嬃鞒潭际窍嗤挠羟帷ixin類(lèi)提供.list()和.create()等操作,然后我們將這些get和post方法明確地綁定到適當(dāng)?shù)牟僮魃衔牧簟J惯@種類(lèi)型的代碼極大減少好唯。

四、基于GenericAPIView和Mixin擴(kuò)展類(lèi)的子類(lèi)

到目前為止燥翅,使用Mixin的擴(kuò)展類(lèi)已經(jīng)讓我們的代碼量足夠簡(jiǎn)潔了骑篙,但Rest framework還進(jìn)行了進(jìn)一步的封裝,在符合條件的情況下可以連定義get森书、post等方法及return的語(yǔ)句也不用再我們自己寫(xiě)靶端。

  1. 可用子類(lèi)試圖介紹
    一共內(nèi)置了9個(gè)可用子類(lèi)試圖
子類(lèi)視圖類(lèi) 作用 對(duì)應(yīng)方法
CreateAPIView 新建 post
ListAPIView 查詢所有 get
RetireveAPIView 查詢指定 get
DestoryAPIView 刪除指定 delete
UpdateAPIView 更新指定 put
ListCreateAPIView 查詢所有及創(chuàng)建 post谎势、get
RetrieveUpdateAPIView 查詢指定及更新 get、put
RetrieveDestoryAPIView 查詢指定及刪除 get杨名、delete
RetrieveUpdateDestoryAPIView 查詢指定脏榆、更新、刪除 get台谍、put姐霍、delete
  1. 使用代碼示例
    只需要不過(guò)10行代碼,就可以實(shí)現(xiàn)最初基于Django的View類(lèi)時(shí)需要寫(xiě)的100多行代碼效果典唇。
    需要我們自己實(shí)現(xiàn)的只有數(shù)據(jù)集的定義及序列化器的定義镊折,其余都基于序列化器進(jìn)行了封裝完成。
from . models import BookInfo
from .serializers import BookModelSerializer
from rest_framework.generics import ListCreateAPIView, RetrieveUpdateDestroyAPIView


class BooksAPIView(ListCreateAPIView):
    serializer_class = BookModelSerializer
    queryset = BookInfo.objects.all()

class BookAPIView(RetrieveUpdateDestroyAPIView):
    serializer_class = BookModelSerializer
    queryset = BookInfo.objects.all()

3.源碼示例
其實(shí)源碼內(nèi)就是封裝了對(duì)方法的定義及return

class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
                                   mixins.UpdateModelMixin,
                                   mixins.DestroyModelMixin,
                                   GenericAPIView):
    """
    Concrete view for retrieving, updating or deleting a model instance.
    """
    def get(self, request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.update(request, *args, **kwargs)

    def patch(self, request, *args, **kwargs):
        return self.partial_update(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

總結(jié)

我用自己的話總結(jié)了這些不同的類(lèi)到底實(shí)現(xiàn)了什么功能介衔,可能有欠妥的地方恨胚,歡迎提出。

  • Serializer:構(gòu)建序列化器炎咖,視圖函數(shù)內(nèi)不再需要自己構(gòu)造鍵值對(duì)數(shù)據(jù)格式赃泡。

  • Response:DRF提供的Response對(duì)象返回?cái)?shù)據(jù)時(shí),不需要再次轉(zhuǎn)換數(shù)據(jù)格式乘盼,只需將request升熊。data傳遞給它即可,它能完成自動(dòng)處理绸栅。

  • APIView:基本DRF視圖類(lèi)级野,提供了新的Request類(lèi)。使用request.data可直接接收轉(zhuǎn)換后的數(shù)據(jù)粹胯。

  • GenericAPIView:基于APIView蓖柔,從視圖函數(shù)中提取出了序列化器和查詢集,主要用于配合Mixin類(lèi)使用风纠。

  • Mixin擴(kuò)展類(lèi)ListModelMixin等:基于object况鸣,視圖類(lèi)使用時(shí)需要同時(shí)繼承Mixin類(lèi)和Generic類(lèi)。此處實(shí)現(xiàn)了邏輯代碼封裝竹观,將數(shù)據(jù)接收镐捧、查詢、驗(yàn)證臭增、響應(yīng)都封裝在了list懂酱、create、retrive速址、update玩焰、destroy方法里面由驹,只需再調(diào)用這些封裝好的方法即可芍锚。

  • 擴(kuò)展類(lèi)子類(lèi)CreateAPIView等:將方法的定義和return返回都封裝了昔园,我們?cè)谝晥D類(lèi)中需要做的只剩指定序列化器與查詢集,其繼承類(lèi)將完成剩下的所有并炮。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末默刚,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子逃魄,更是在濱河造成了極大的恐慌荤西,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件伍俘,死亡現(xiàn)場(chǎng)離奇詭異邪锌,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)癌瘾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)觅丰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人妨退,你說(shuō)我怎么就攤上這事妇萄。” “怎么了咬荷?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵冠句,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我幸乒,道長(zhǎng)懦底,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任罕扎,我火速辦了婚禮基茵,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘壳影。我一直安慰自己拱层,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布宴咧。 她就那樣靜靜地躺著根灯,像睡著了一般。 火紅的嫁衣襯著肌膚如雪掺栅。 梳的紋絲不亂的頭發(fā)上烙肺,一...
    開(kāi)封第一講書(shū)人閱讀 51,165評(píng)論 1 299
  • 那天,我揣著相機(jī)與錄音氧卧,去河邊找鬼桃笙。 笑死,一個(gè)胖子當(dāng)著我的面吹牛沙绝,可吹牛的內(nèi)容都是我干的搏明。 我是一名探鬼主播鼠锈,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼星著!你這毒婦竟也來(lái)了购笆?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤虚循,失蹤者是張志新(化名)和其女友劉穎同欠,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體横缔,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡铺遂,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了茎刚。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片娃循。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖斗蒋,靈堂內(nèi)的尸體忽然破棺而出捌斧,到底是詐尸還是另有隱情,我是刑警寧澤泉沾,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布捞蚂,位于F島的核電站,受9級(jí)特大地震影響跷究,放射性物質(zhì)發(fā)生泄漏姓迅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一俊马、第九天 我趴在偏房一處隱蔽的房頂上張望丁存。 院中可真熱鬧,春花似錦柴我、人聲如沸解寝。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)聋伦。三九已至,卻和暖如春界睁,著一層夾襖步出監(jiān)牢的瞬間觉增,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工翻斟, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留逾礁,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓访惜,卻偏偏與公主長(zhǎng)得像嘹履,于是被迫代替她去往敵國(guó)和親腻扇。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容