摘要:下面我們來(lái)說(shuō)說(shuō)如何使用來(lái)減輕序列化模型的工作量。主要包括如下個(gè)步驟定義模式序列化模型下面我們分別來(lái)看看。不得不說(shuō)這個(gè)庫(kù)對(duì)于序列化模型其實(shí)挺實(shí)用的。
原文地址:
http://52sox.com/use-python-serialization-orm-data-to-json/
相信使用Python做Web開發(fā)的朋友都會(huì)遇到這樣1個(gè)問(wèn)題,那就是在項(xiàng)目開發(fā)中使用模型框架,比如SQLAlchemy、Peewee,我們?cè)谧鯮ESTful接口時(shí)如何將這些模型序列化為JSON數(shù)據(jù)。
關(guān)于這個(gè)問(wèn)題,跟隔壁那位搞Python的哥們有關(guān)系。我不得不佩服這位哥們竟然自己寫了1套ORM框架,而且用起來(lái)的那么遛,不得不讓我汗顏。
但是,在給前端提供接口的時(shí)候,如何序列化為JSON數(shù)據(jù)確實(shí)困擾了我們那么一陣子,畢竟占據(jù)我們很大一部分時(shí)間來(lái)進(jìn)行序列化操作。
這里,我們使用peewee來(lái)定義1個(gè)簡(jiǎn)單的例子來(lái)說(shuō)明:
from peewee import SqliteDatabase from peewee import Model, CharField, DateField, BooleanField, ForeignKeyField db = SqliteDatabase("dev.sqlite3") class BaseModel(Model): class Meta: database = db class Person(BaseModel): name = CharField(max_length= 20) birthday = DateField() sex = BooleanField() class Pet(BaseModel): owner = ForeignKeyField(Person, related_name= "pets") name = CharField(max_length= 10) animal_type = CharField(max_length= 20)
在這里我們定義了Person和Pet這2個(gè)模型,每個(gè)Person可能有1個(gè)Pet的寵物。
我們插入一些數(shù)據(jù),現(xiàn)在假設(shè)我們現(xiàn)在有如下的數(shù)據(jù):
sqlite> select * from person; 1|Bob|1960-01-15|1 2|Grandma|1935-03-01|0 3|Herb|1950-05-05|1 sqlite> select * from pet; 1|1|Kitty|cat 2|3|Fido|dog 3|3|Mittens|cat 4|2|Jack|cat
現(xiàn)在,我們假設(shè)我們接口需要返回的接口是每個(gè)用戶的名稱、生日及其對(duì)應(yīng)的寵物的信息。
我們可以通過(guò)連表的方式輕松的獲取到我們需要的數(shù)據(jù):
query=Person.select(Person,Pet).join(Pet)
那么我們?cè)趺磳⑦@個(gè)模型數(shù)據(jù)轉(zhuǎn)換為我們需要的JSON數(shù)據(jù)呢?一般情況下,我們會(huì)這樣操作:
data = [] for person in query.aggregate_rows(): d={} d["username"] = person.name d["birthday"] = person.birthday d["pet"] = [] for pet in person.pets: o = {} o["name"] = pet.name o["animal_type"] = pet.animal_type d["pet"].append(o) data.append(d)
最后我們將得到如下的結(jié)果:
[{"birthday": datetime.date(1960, 1, 15), "pet": [{"animal_type": u"cat", "name": u"Kitty"}], "username": u"Bob"}, {"birthday": datetime.date(1950, 5, 5), "pet": [{"animal_type": u"dog", "name": u"Fido"}, {"animal_type": u"cat", "name": u"Mittens"}], "username": u"Herb"}, {"birthday": datetime.date(1935, 3, 1), "pet": [{"animal_type": u"cat", "name": u"Jack"}], "username": u"Grandma"}]
可以看到,這么1個(gè)簡(jiǎn)單的例子,我們已經(jīng)對(duì)序列化操作處理的已經(jīng)夠嗆的。對(duì)于那些更為復(fù)雜的模型,我們預(yù)計(jì)只有哭的份了。
因此,我們希望能找到1個(gè)庫(kù)可以減輕我們的工作量,于是我們找到了1個(gè)marshallow的庫(kù)。
下面我們來(lái)說(shuō)說(shuō)如何使用marshallow來(lái)減輕序列化模型的工作量。
主要包括如下2個(gè)步驟:
定義模式
序列化模型
下面我們分別來(lái)看看。
定義模式如果你使用過(guò)Flask-RESTful,你應(yīng)該知道該庫(kù)提供了1個(gè)marshal_with的函數(shù)。其中我們就需要定義我們給定字段返回的數(shù)據(jù)類型,但是Flask-RESTful沒(méi)有提供字段不同返回的操作。
我們通過(guò)如下的方式導(dǎo)入模式及其對(duì)應(yīng)的字段:
from marshmallow import Schema, fields
接下來(lái),我們定義1個(gè)繼承自Schema的類,然后定義其對(duì)應(yīng)的字段:
class PetSchema(Schema): name = fields.String() animal_type = fields.String() class PersonSchema(Schema): name = fields.String(dump_to = "username") birthday = fields.Date() pets = fields.Nested(PetSchema,dump_to="pet",many=True)
由于這里,我們將用戶的name屬性修改為username,因此我們需要在字段中使用dump_to參數(shù)將其修改為我們需要的字段。另外,用戶的pet字段對(duì)應(yīng)的是寵物的信息,因此我們采用嵌套模式來(lái)實(shí)現(xiàn)這樣需求。
序列化模型上面我們已經(jīng)定義好了我們的模式了,下一步是序列化模型的操作了。
我們可以這樣來(lái)操作:
query=Person.select(Person, Pet).join(Pet)
接著,我們實(shí)例化我們的模式,然后傳入需要序列化的模型:
person, error = PersonSchema(many = True).dumps(query.aggregate_rows())
在這里,我們調(diào)用PersonSchema實(shí)例的dumps來(lái)生成JSON數(shù)據(jù),另外它還有1個(gè)dump方法用于生成Python對(duì)象。由于我們的渲染的數(shù)據(jù)有多條,因此我們需要在實(shí)例化PersonSchema類時(shí)傳入關(guān)鍵字參數(shù)many為True,不然沒(méi)有任何數(shù)據(jù)。
通過(guò)這種方式,PersonSchema會(huì)查看它自己的屬性,將數(shù)據(jù)模型中對(duì)應(yīng)的數(shù)據(jù)先序列化出來(lái),然后是查詢嵌套模式中的字段,如果符合對(duì)應(yīng)的名稱則將其序列化出來(lái),最后我們將得到這樣的數(shù)據(jù):
[ { "username": "Bob", "pet": [ { "animal_type": "cat", "name": "Kitty" } ], "birthday": "1960-01-15" }, { "username": "Herb", "pet": [ { "animal_type": "dog", "name": "Fido" }, { "animal_type": "cat", "name": "Mittens" } ], "birthday": "1950-05-05" }, { "username": "Grandma", "pet": [ { "animal_type": "cat", "name": "Jack" } ], "birthday": "1935-03-01" } ]
可以看到,通過(guò)marshallow得到的結(jié)果與之前我們編寫的序列化操作的結(jié)果是一樣的。
不得不說(shuō),marshallow這個(gè)庫(kù)對(duì)于序列化模型其實(shí)挺實(shí)用的。當(dāng)然對(duì)于復(fù)雜的模型,我們需要利用合適的方式將其搜索出來(lái),不然還是序列化不了的。
參考文章:
https://marshmallow.readthedocs.io/en/latest/quickstart.html
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/38028.html
摘要:據(jù)公告稱,和的包裝庫(kù)使用了不安全的函數(shù)來(lái)反序列化編碼的機(jī)器學(xué)習(xí)模型。簡(jiǎn)單來(lái)看,序列化將對(duì)象轉(zhuǎn)換為字節(jié)流。據(jù)悉,本次漏洞影響與版本,的到版本均受影響。作為解決方案,在宣布棄用之后,團(tuán)隊(duì)建議開發(fā)者以替代序列化,或使用序列化作為替代。 ...
摘要:在本文中,我們將學(xué)習(xí)構(gòu)建自定義新聞?wù)Z料庫(kù)并分別注釋與興趣相對(duì)應(yīng)的大量文章。為此,我們將使用。我們將使用另一個(gè)名為的免費(fèi)服務(wù)。我正在使用單擊創(chuàng)建觸發(fā)器完成。我們將使用相同的調(diào)度庫(kù)來(lái)運(yùn)行我們?cè)诘谡聵?gòu)建應(yīng)用程序以查找廉價(jià)機(jī)票中使用的代碼。 showImg(https://segmentfault.com/img/remote/1460000019191794); 來(lái)源 | 愿碼(Chain...
摘要:查詢集表示從數(shù)據(jù)庫(kù)中取出來(lái)的對(duì)象的集合。例如,返回包含數(shù)據(jù)庫(kù)中所有對(duì)象的一個(gè)查詢集。最后的結(jié)果仍然是一個(gè)查詢集,它包含標(biāo)題以開頭發(fā)布日期在年月日至當(dāng)天之間的所有記錄。一般來(lái)說(shuō),只有在請(qǐng)求查詢集的結(jié)果時(shí)才會(huì)到數(shù)據(jù)庫(kù)中去獲取它們。 Django數(shù)據(jù)庫(kù)操作 創(chuàng)建對(duì)象 Django 使用一種直觀的方式把數(shù)據(jù)庫(kù)表中的數(shù)據(jù)表示成Python 對(duì)象: 一個(gè)模型類代表數(shù)據(jù)庫(kù)中的一個(gè)表,一個(gè)模型類的實(shí)...
摘要:方法對(duì)應(yīng)的是方法,它反序列化一個(gè)字典為數(shù)據(jù)結(jié)構(gòu)。某些例如和內(nèi)置了驗(yàn)證器驗(yàn)證集合時(shí),錯(cuò)誤字典將基于無(wú)效字段的索引作為鍵通過(guò)給的參數(shù)傳遞對(duì)象,可以執(zhí)行額外的驗(yàn)證驗(yàn)證函數(shù)可以返回布爾值或拋出異常。 快速上手 Declaring Schemas 首先創(chuàng)建一個(gè)基礎(chǔ)的user模型(只是為了演示,并不是真正的模型): import datetime as dt class User(object)...
閱讀 3403·2021-11-24 09:38
閱讀 3189·2021-11-22 09:34
閱讀 2098·2021-09-22 16:03
閱讀 2349·2019-08-29 18:37
閱讀 371·2019-08-29 16:15
閱讀 1761·2019-08-26 13:56
閱讀 853·2019-08-26 12:21
閱讀 2198·2019-08-26 12:15