2016/07/01 · 實踐專案 · orm, web
原文出處: 我勒個去
相信使用python做web開發的朋友都會遇到這樣1個問題,那就是在專案開發中使用模型框架,比如sqlalchemy、peewee,我們在做restful介面時如何將這些模型序列化為json資料。
關於這個問題,跟隔壁那位搞python的哥們有關係。我不得不佩服這位哥們竟然自己寫了1套orm框架,而且用起來的那麼遛,不得不讓我汗顏。
但是,在給前端提供介面的時候,如何序列化為json資料確實困擾了我們那麼一陣子,畢竟佔據我們很大一部分時間來進行序列化操作。
這裡,我們使用peewee來定義1個簡單的例子來說明:
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()
*** = booleanfield()
class pet(basemodel):
owner = foreignkeyfield(person, related_name= 'pets')
name = charfield(max_length= 10)
animal_type = charfield(max_length= 20)
在這裡我們定義了person和pet這2個模型,每個person可能有1個pet的寵物。
我們插入一些資料,現在假設我們現在有如下的資料:
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
現在,我們假設我們介面需要返回的介面是每個使用者的名稱、生日及其對應的寵物的資訊。
我們可以通過連表的方式輕鬆的獲取到我們需要的資料:
query=person.select(person,pet).join(pet)
那麼我們怎麼將這個模型資料轉換為我們需要的json資料呢?一般情況下,我們會這樣操作:
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
最後我們將得到如下的結果:
,'username': u'bob'},,],
'username': u'herb'},
],'username': u'grandma'}]
可以看到,這麼1個簡單的例子,我們已經對序列化操作處理的已經夠嗆的。對於那些更為複雜的模型,我們預計只有哭的份了。
因此,我們希望能找到1個庫可以減輕我們的工作量,於是我們找到了1個marshallow的庫。
下面我們來說說如何使用marshallow來減輕序列化模型的工作量。
主要包括如下2個步驟:
下面我們分別來看看。
如果你使用過flask-restful,你應該知道該庫提供了1個marshal_with
的函式。其中我們就需要定義我們給定字段返回的資料型別,但是flask-restful沒有提供字段不同返回的操作。
我們通過如下的方式匯入模式及其對應的字段:
from marshmallow import schema, fields
接下來,我們定義1個繼承自schema的類,然後定義其對應的字段:
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
引數將其修改為我們需要的字段。另外,使用者的pet欄位對應的是寵物的資訊,因此我們採用巢狀模式來實現這樣需求。
上面我們已經定義好了我們的模式了,下一步是序列化模型的操作了。
我們可以這樣來操作:
query=person.select(person, pet).join(pet)
接著,我們例項化我們的模式,然後傳入需要序列化的模型:
person, error = personschema(many = true).dumps(query.aggregate_rows())
在這裡,我們呼叫personschema例項的dumps來生成json資料,另外它還有1個dump方法用於生成python物件。由於我們的渲染的資料有多條,因此我們需要在例項化personschema類時傳入關鍵字引數many為true,不然沒有任何資料。
通過這種方式,personschema會檢視它自己的屬性,將資料模型中對應的資料先序列化出來,然後是查詢巢狀模式中的字段,如果符合對應的名稱則將其序列化出來,最後我們將得到這樣的資料:
"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"
可以看到,通過marshallow得到的結果與之前我們編寫的序列化操作的結果是一樣的。
不得不說,marshallow這個庫對於序列化模型其實挺實用的。當然對於複雜的模型,我們需要利用合適的方式將其搜尋出來,不然還是序列化不了的。
序列化(模型序列化 序列化巢狀)
from rest framework import serializers from meituan.models import merchant,class merchantserializer serializers.modelserializer class meta model merch...
python 序列化模組 python 序列化模組
一 介紹 1 分類 序列化 資料型別 字串 反序列化 字串 資料型別 2 作用 檔案傳輸和檔案儲存需要將資料型別轉換成字串 二 序列號模組分類 1 json 優點 程式語言中的英語,同用語言 缺點 資料型別少 數字 字串 列表 字典 元祖 通過列表進行的 2 pickle 優點 python的所有資...
Python 序列化和反序列化
在spark中使用廣播變數時,選擇合適的序列化格式是非常重要的。這裡重點講的是python中的序列化。1.序列化和反序列化 序列化就是把資料變成可儲存或可傳輸的過程的,只有序列化後的資料才可以寫入到磁碟或者通過網路傳輸到spark集群的其他節點上。反序列化則相反,反序列就是把序列化的變數重新轉到記憶...