Django-DRF-序列化模型實戰(zhàn)(一)

前言:本文帶領(lǐng)大家了解django-rest-framework “序列化模型”的一些使用及知識點芹橡,通過實戰(zhàn)演示進一步讓大家能簡單看懂,并且上手操作磺樱,了解DRF的強大誓竿。

一磅网、App創(chuàng)建與管理

在講解本文主題“序列化模型”之前,我們需要創(chuàng)建一個app來進行實際的演示烤黍,因此你想更深入的了解學(xué)習(xí)本文知識點的話知市,建議你跟著一起操作傻盟。

首先創(chuàng)建一個app:

$ python manage.py startapp idcs

隨著項目越來越龐大,項目里的app越來越多嫂丙,因此需要將所有app進行管理起來娘赴,管理方法如下

創(chuàng)建管理app的目錄:

$ mkdir apps
$ mv idcs apps

需要知道的是,創(chuàng)建的app也是一個python的模塊跟啤,我們后面也可以將一些非app的模塊放到這里面诽表,目的是便于管理。

因為目錄結(jié)構(gòu)有了變化隅肥,Django找不到創(chuàng)建的app了竿奏,所以需要我們配置一下,告訴Django在哪里能找到我們創(chuàng)建的app腥放。方法如下
Django加載apps目錄:

$ vim ops/settings.py

import os
import sys  # 先導(dǎo)入sys模塊
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, os.path.join(BASE_DIR, 'apps'))  # 增加這一行

INSTALLED_APPS = [
······
    'idcs.apps.IdcsConfig',        #在apps列表里添加剛剛創(chuàng)建的idcs app
]

需要在Django的配置文件里加載它泛啸,這里使用sys模塊將apps所在的路徑插入到sys.path中,這樣Django在尋找app的時候就知道去哪找了秃症。

idcs創(chuàng)建urls.py文件
上面通過startapp創(chuàng)建好app后候址,你會發(fā)現(xiàn)app里沒有urls.py文件。嘿嘿嘿种柑,如果沒有這個文件岗仑,你啟動Django項目試試?它保證不會任性不出錯(諷刺)聚请。荠雕。。

因此驶赏,我們需要自己來創(chuàng)建這個文件炸卑,并寫下urlpatterns字段。

$ vim apps/idcs/urls.py
urlpatterns = [
]

配置路由:
app的導(dǎo)入和url問題都搞定了母市,接下來需要在全局urls.py文件里配置idcs這個app的路由關(guān)系

$ vim ops/urls.py
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^idcs/', include("idcs.urls")),     # 默認無法識別矾兜,Pycharm工具配置自動識別方法:右擊“apps”目錄 -->Mark -->Source Root 
]

安裝DRF:

配置好app后损趋,我們順便把DRF也安裝和配置一下患久,非常簡單快速。

1浑槽、安裝

$ pip install django-rest-framework

2蒋失、配置Django加載DRF

Django使用drf比較簡單,直接在apps列表里寫入如下模塊即可完成桐玻,后面就等著使用了篙挽。

$ vim ops/settings.py

INSTALLED_APPS = [
······
    'rest_framework',
]

好,完事镊靴。

二铣卡、序列化模型

2.1链韭、同步Idc模型

在models模型文件里創(chuàng)建字段如下,并使用下面給出的命令快速同步到數(shù)據(jù)庫中

$ vim idcs/models.py

class Idc(models.Model):
    name    = models.CharField("機房名稱",max_length=32)
    address = models.CharField("機房地址",max_length=256)
    phone  = models.CharField("聯(lián)系人",max_length=15)
    email  = models.EmailField("郵件地址",default="null")
    letter  = models.CharField("IDC簡稱",max_length=5)

    def __str__(self):
        return self.name
    class Meta:
        db_table = 'resource_idc'

$ python manage.py showmigrations
$ python manage.py migrate
$ python manage.py makemigrations idcs
$ python manage.py migrate idcs

2.2煮落、定義序列化類

在idc app目錄下新建一個文件serializers.py敞峭,因為是做序列化,而序列化是針對模型的蝉仇,所以需要跟模型文件models.py在同一個目錄下

$ vim idcs/serializers.py

from rest_framework import serializers   # 導(dǎo)入這個模塊旋讹,來使用序列化

# 定義并編寫序列化類
class IdcSerializer(serializers.Serializer):
    """
    Idc, 序列化類
    """
    id      = serializers.IntegerField(read_only=True) # 處理只讀
    name    = serializers.CharField(required=True, max_length=32) # 字段必須傳, 最大限制32個字符
    address = serializers.CharField(required=True, max_length=256)
    phone  = serializers.CharField(required=True, max_length=15)
    email  = serializers.CharField(required=True)
    letter  = serializers.CharField(required=True, max_length=5)

2.3、使用序列化

通過python mamage.py shell往IDC模型里添加兩條記錄

In [1]: from idcs.models import Idc
In [2]: idc = Idc()
In [3]: idc.name = '亦莊機房'
In [4]: idc.address = '北京亦莊機房'
In [5]: idc.phone = '12312341234'
In [6]: idc.email = 'nick@qq.com'
In [7]: idc.letter = 'yz'
In [8]: idc.save()
In [9]:
In [9]: idc.id = None
In [10]: idc.name = '兆維機房'
In [11]: idc.address = '兆維工業(yè)園'
In [12]: idc.phone = '18512341234'
In [13]: idc.email = 'zw@qq.com'
In [14]: idc.letter = 'zw'
In [15]: idc.save()

2.3.1轿衔、正向序列化

正向序列化的定義:從“數(shù)據(jù)庫”里獲取數(shù)據(jù)并序列化后返回標準JSON類型的數(shù)據(jù)給前端

具體使用序列化的操作如下:

In [17]: from idcs.serializers import IdcSerializer # 導(dǎo)入序列化類

In [18]: idc = Idc.objects.get(pk=1)  # 獲取一條IDC信息沉迹,等待序列化

In [19]: idc
Out[19]: <Idc: 亦莊機房>

In [20]: serializers = IdcSerializer(idc)  # 將idc對象傳給序列化類 進行序列化操作后存放到一個變量里,序列化完成害驹。

In [21]: serializers # 輸出結(jié)果鞭呕,會把序列化里的字段給打印出來
Out[21]:
IdcSerializer(<Idc: 亦莊機房>):
    id = IntegerField()
    name = CharField()
    address = CharField()
    phone = CharField()
    email = CharField()
    letter = CharField()

In [23]: serializers.data # 通過.data能獲取到所有的數(shù)據(jù)
Out[23]: {'id': 1, 'name': '亦莊機房', 'address': '北京亦莊機房', 'phone': '12312341234', 'email': 'nick@qq.com', 'letter': 'yz'}

In [24]: a = serializers.data

In [25]: type(a)
Out[25]: rest_framework.utils.serializer_helpers.ReturnDict

能看到serializers.data的類型是一個ReturnDict,而我們最終需求是需要轉(zhuǎn)換成Json類型返回給前端的宛官,那如何轉(zhuǎn)換呢琅拌?

使用drf內(nèi)置模塊將結(jié)果轉(zhuǎn)換成標準的json數(shù)據(jù):

In [26]: from rest_framework.renderers import JSONRenderer

In [27]: ?JSONRenderer
Init signature: JSONRenderer()
Docstring:      Renderer which serializes to JSON.
File:          ~/Projects/Python/v3/VirtualSource/venv/lib/python3.6/site-packages/rest_framework/renderers.py
Type:          type

In [28]: jr = JSONRenderer() # 實例化

In [29]: jr.render(serializers.data) # 使用render方法將結(jié)果轉(zhuǎn)換成標準的Json數(shù)據(jù)
Out[29]: b'{"id":1,"name":"\xe4\xba\xa6\xe5\xba\x84\xe6\x9c\xba\xe6\x88\xbf","address":"\xe5\x8c\x97\xe4\xba\xac\xe4\xba\xa6\xe5\xba\x84\xe6\x9c\xba\xe6\x88\xbf","phone":"12312341234","email":"nick@qq.com","letter":"yz"}'

In [30]: content = jr.render(serializers.data)  # 拿到這個數(shù)據(jù),就可以直接返回給前端了摘刑。

正向序列化多條記錄

In [1]: from idcs.models import  Idc

In [2]: from idcs.serializers import IdcSerializer

In [3]: Idc.objects.all()
Out[3]: <QuerySet [<Idc: 亦莊機房>, <Idc: 兆維機房>]>

In [4]: data = IdcSerializer(Idc.objects.all(), many=True)  # 關(guān)鍵在于這一步进宝,使用many=True聲明傳入的是多個object對象

In [5]: data
Out[15]: 
IdcSerializer(<QuerySet [<Idc: 亦莊機房>, <Idc: 兆維機房>]>, many=True):
    id = IntegerField()
    name = CharField()
    address = CharField()
    phone = CharField()
    email = CharField()
    letter = CharField()

In [6]: from rest_framework.renderers import  JSONRenderer

In [6]: content = JSONRenderer().render(data.data)

In [7]: content
Out[7]: 
b'[{"id":1,"name":"\xe4\xba\xa6\xe5\xba\x84\xe6\x9c\xba\xe6\x88\xbf","address":"\xe5\x8c\x97\xe4\xba\xac\xe4\xba\xa6\xe5\xba\x84\xe6\x9c\xba\xe6\x88\xbf","phone":"12312341234","email":"nick@qq.com","letter":"yz"},{"id":2,"name":"\xe5\x85\x86\xe7\xbb\xb4\xe6\x9c\xba\xe6\x88\xbf","address":"\xe5\x85\x86\xe7\xbb\xb4\xe5\xb7\xa5\xe4\xb8\x9a\xe5\x9b\xad","phone":"18512341234","email":"zw@qq.com","letter":"zw"}]'

小結(jié):

序列化的過程如下

1. mysql獲取數(shù)據(jù)

2. queryset = Idc.objects.all() #獲取單個或所有idc對象

3. content = JSORNRenderer().render(queryset) # 轉(zhuǎn)換成標準Json數(shù)據(jù)

4. HttpResponse(content) # 返回給前端

重點:
上面的小結(jié)里,能看到序列化的過程枷恕,那序列化還能做些什么事情呢党晋?它可以驗證前端傳入過來的數(shù)據(jù),并且添加徐块、更新這些數(shù)據(jù)未玻。

2.3.2、反向序列化
反向序列化的定義從“前端接口”接收添加的數(shù)據(jù)并序列化后返回一個object對象給后端胡控,而且可以進行數(shù)據(jù)驗證以及添加到數(shù)據(jù)庫的操作扳剿。

編寫序列化驗證、創(chuàng)建昼激、更新庇绽、保存規(guī)則:

$ vim idcs/serializers.py

from rest_framework import serializers
from .models import Idc  # 需要導(dǎo)入Idc模型

class IdcSerializer(serializers.Serializer):
    """
    Idc, 序列化類
    """
    id      = serializers.IntegerField(read_only=True) # 處理只讀
    name    = serializers.CharField(required=True, max_length=32) # 字段必須傳, 最大限制32個字符
    address = serializers.CharField(required=True, max_length=256)
    phone  = serializers.CharField(required=True, max_length=15)
    email  = serializers.CharField(required=True)
    letter  = serializers.CharField(required=True, max_length=5)


    def create(self, validated_data):
        return Idc.objects.create(**validated_data)  # 調(diào)用Idc模型進行create操作

    def update(self, instance, validated_data): # 參數(shù)介紹:instance是當前的對象,validated_data是處理過的干凈數(shù)據(jù)
        '''
        update方法可以允許修改什么字段橙困,如果有不需要修改的字段瞧掺,不寫即可
        '''
        instance.name      = validated_data.get("name",instance.name)
        instance.address    = validated_data.get("address",instance.name)
        instance.phone      = validated_data.get("phone",instance.name)
        instance.email      = validated_data.get("email",instance.name)
        instance.save()
        return instance

注意:在“正向序列化”的時候,CharField字段里的參數(shù)都沒有作用凡傅,只有在“反向序列化”是才會有作用辟狈。

反向序列化的操作過程:

In [1]: from idcs.serializers import IdcSerializer

In [2]: data = {'id': 1,'name': '數(shù)北機房','address': '北京數(shù)北機房','phone': '12312341234','email': 'aaa@123.com','letter': 'yz'}In [2]: data = {'id': 1,
  ...:  'name': '亦莊機房',
  ...:  'address': '北京亦莊機房',
  ...:  'phone': '12345678',
  ...:  'email': 'aaa@123.com',
  ...:  'letter': 'yz'}   # 這里的data數(shù)據(jù)模擬前端接口傳進來的數(shù)據(jù)哈

In [3]: serializer = IdcSerializer(data=data) # 將Json格式的數(shù)據(jù)傳入IdcSerializer進行序列化

In [4]: serializer # 得到序列化后的結(jié)果
Out[4]: 
IdcSerializer(data={'id': 1, 'name': '亦莊機房', 'address': '北京亦莊機房', 'phone': '12345678', 'email': 'rock@51reboot.com', 'letter': 'yz'}):
    id = IntegerField(read_only=True)
    name = CharField(max_length=32, required=True)
    address = CharField(max_length=256, required=True)
    phone = CharField(max_length=15, required=True)
    email = EmailField(required=True)
    letter = CharField(max_length=5, required=True)

In [5]: serializer.is_valid()  # 查看驗證是否通過,調(diào)用的是(required=True, max_length=32)這些條件參數(shù)哈
Out[5]: True

In [6]: serializer.validated_data # 通過validated_data獲取數(shù)據(jù)
Out[6]: 
OrderedDict([('name', '亦莊機房'),
            ('address', '北京亦莊機房'),
            ('phone', '12345678'),
            ('email', 'aaa@123.com'),
            ('letter', 'yz')])

In [7]: del data["id"]  # 刪除id數(shù)據(jù)后方便添加到數(shù)據(jù)庫中

In [8]: data
Out[8]: 
{'name': '亦莊機房',
'address': '北京亦莊機房',
'phone': '12345678',
'email': 'aaa@123.com',
'letter': 'yz'}

In [9]: serializer = IdcSerializer(data=data) # 重新執(zhí)行驗證

In [10]: serializer.is_valid()
Out[10]: True

In [11]: serializer.save()  # 這里的save調(diào)用了IdcSerializer類里我們寫的create方法
Out[11]: <Idc: 亦莊機房>

上面在編寫IdcSerializer序列化類的時候,寫了create和update方法哼转,那么這兩個方法有什么用呢明未?又是如何使用的呢?

重點概念Django能自動判斷你提交的請求是需要增加壹蔓,判斷的標準是基于ID亚隅,如果傳入的數(shù)據(jù)里有ID的話,那么認為你是需要進行修改庶溶,沒有ID則認為是需要進行創(chuàng)建

在上面操作細節(jié)中煮纵,在執(zhí)行serializer.save() 方法時,事實上是調(diào)用了IdcSerializer類的create方法偏螺,就是基于Django智能判斷來實現(xiàn)的行疏。

2.4、序列化總結(jié)

1套像、正向序列化

1. 拿到quertset
2. 將quertset給序列化類
    serializer = IdcSerializer(idc)
    serializer = IdcSerializer(Idc.objects.all(), many=True)
3. 轉(zhuǎn)JSON
    JSONRenderer().render(serializer.data)

2酿联、反向序列化

data = JSONRenderer().parse(content)
serializer = IdcSerializer(data=data)
serializer.is_valid()
serializer.save()

正向序列化:從數(shù)據(jù)庫里拿出來數(shù)據(jù),然后返回Json給前端

反向序列化:從前端接口拿到數(shù)據(jù)(data)夺巩,將數(shù)據(jù)轉(zhuǎn)換成數(shù)據(jù)流贞让,然后序列化驗證后,保存到數(shù)據(jù)庫中柳譬。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末喳张,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子美澳,更是在濱河造成了極大的恐慌销部,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,919評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件制跟,死亡現(xiàn)場離奇詭異舅桩,居然都是意外死亡,警方通過查閱死者的電腦和手機雨膨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評論 3 392
  • 文/潘曉璐 我一進店門擂涛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人聊记,你說我怎么就攤上這事撒妈。” “怎么了甥雕?”我有些...
    開封第一講書人閱讀 163,316評論 0 353
  • 文/不壞的土叔 我叫張陵踩身,是天一觀的道長胀茵。 經(jīng)常有香客問我社露,道長,這世上最難降的妖魔是什么琼娘? 我笑而不...
    開封第一講書人閱讀 58,294評論 1 292
  • 正文 為了忘掉前任峭弟,我火速辦了婚禮附鸽,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瞒瘸。我一直安慰自己坷备,他們只是感情好,可當我...
    茶點故事閱讀 67,318評論 6 390
  • 文/花漫 我一把揭開白布情臭。 她就那樣靜靜地躺著省撑,像睡著了一般。 火紅的嫁衣襯著肌膚如雪俯在。 梳的紋絲不亂的頭發(fā)上竟秫,一...
    開封第一講書人閱讀 51,245評論 1 299
  • 那天,我揣著相機與錄音跷乐,去河邊找鬼肥败。 笑死,一個胖子當著我的面吹牛愕提,可吹牛的內(nèi)容都是我干的馒稍。 我是一名探鬼主播,決...
    沈念sama閱讀 40,120評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼浅侨,長吁一口氣:“原來是場噩夢啊……” “哼纽谒!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起如输,我...
    開封第一講書人閱讀 38,964評論 0 275
  • 序言:老撾萬榮一對情侶失蹤佛舱,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后挨决,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體请祖,經(jīng)...
    沈念sama閱讀 45,376評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,592評論 2 333
  • 正文 我和宋清朗相戀三年脖祈,在試婚紗的時候發(fā)現(xiàn)自己被綠了肆捕。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,764評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡盖高,死狀恐怖慎陵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情喻奥,我是刑警寧澤席纽,帶...
    沈念sama閱讀 35,460評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站撞蚕,受9級特大地震影響润梯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,070評論 3 327
  • 文/蒙蒙 一纺铭、第九天 我趴在偏房一處隱蔽的房頂上張望寇钉。 院中可真熱鬧,春花似錦舶赔、人聲如沸扫倡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽撵溃。三九已至,卻和暖如春锥累,著一層夾襖步出監(jiān)牢的瞬間征懈,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評論 1 269
  • 我被黑心中介騙來泰國打工揩悄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留卖哎,地道東北人。 一個月前我還...
    沈念sama閱讀 47,819評論 2 370
  • 正文 我出身青樓删性,卻偏偏與公主長得像亏娜,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蹬挺,可洞房花燭夜當晚...
    茶點故事閱讀 44,665評論 2 354

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