在前后端分離項目中,經(jīng)常需要把ORM模型轉(zhuǎn)化為字典,再將字典轉(zhuǎn)化為JSON格式的字符串。在遇到sqlalchemy_serializer之前,我都是通過類似Java中的反射原理,獲取當前ORM模型的所有字段,然后寫一個to_dict方法來將字段以及他的值封裝成字典。大概的代碼如下所示:
def to_dict(self):
return {c.name: str(getattr(self, c.name)) for c in self.__table__.columns}
這種做法雖然一定程度上方便了開發(fā),但也是帶著枷鎖跳舞,存在以下幾個弊端:
-
無法優(yōu)雅的排除不需要序列化的字段。
-
無法優(yōu)雅的序列化多表之間的關(guān)系。
直到后來我遇到了sqlalchemy_serializer,淚流滿面,這不就是我苦苦尋找的ORM模型序列化庫嗎?使用他序列化ORM模型,讓我?guī)憧纯从卸嗨?
一、安裝:
sqlalchemy-serializer已經(jīng)上架PyPi,因此通過pip命令即可安裝:
pip install SQLAlchemy-serializer
二、基本使用:
如果想要讓某個ORM模型能被序列化,那么只需要在定義模型的時候,讓他繼承自sqlalchemy_serializer.SerializerMixin即可,示例代碼如下:
from sqlalchemy_serializer import SerializerMixin
class UserModel(db.Model, SerizlizerMixin):
__tablename__ = "user"
id = db.Column(db.String(100), primary_key=True, default=shortuuid.uuid)
email = db.Column(db.String(50), unique=True, nullable=False)
username = db.Column(db.String(50), nullable=False)
password = db.Column(db.String(200), nullable=False)
SerizlizerMixin會給ORM模型添加一個to_dict方法,此時你可以通過一行代碼將ORM模型序列化成字典:
user = UserModel.query.filter(...).one()
user_dict = user.to_dict()
上述代碼中將把UsrModel中所有字段都序列化成字典。
三、排除字段:
模型中有的字段不需要被序列化,比如用戶的密碼,那么這時候可以通過設(shè)置rules參數(shù),或者only參數(shù)來指定序列化規(guī)則。比如排除password,那么可以通過如下代碼方式實現(xiàn):
user = UserModel.query.filter(...).one()
user_dict = user.to_dict(rules=('-password',))
上述代碼中在調(diào)用to_dict方法的時候,傳遞了rules參數(shù),并且設(shè)置了-password,其中的-號代表排除的意思,意思是不要序列化password。如果在絕大部分場景下都不需要某些字段,可以把這個規(guī)則寫在模型定義中,這樣所有序列化的時候,都會遵循這個序列化規(guī)則。比如:
class UserModel(db.Model, SerizlizerMixin):
serialize_rules = ("-password", )
__tablename__ = "user"
id = db.Column(db.String(100), primary_key=True, default=shortuuid.uuid)
email = db.Column(db.String(50), unique=True, nullable=False)
username = db.Column(db.String(50), nullable=False)
password = db.Column(db.String(200), nullable=False)
如果需要排除的字段太多了,我們可以通過設(shè)置serialize_only屬性來標記僅僅序列化某些字段。比如:
class UserModel(db.Model, SerizlizerMixin):
serialize_only = ("id", "username")
__tablename__ = "user"
id = db.Column(db.String(100), primary_key=True, default=shortuuid.uuid)
email = db.Column(db.String(50), unique=True, nullable=False)
username = db.Column(db.String(50), nullable=False)
password = db.Column(db.String(200), nullable=False)
上述代碼在序列化的時候,就只會序列化id和username兩個字段了。
四、遞歸序列化模型和樹:
sqlalchemy_serializer會默認序列化定義好關(guān)系的模型,比如有UserModel和PostModel兩個模型:
class UserModel(db.Model, SerizlizerMixin):
serialize_rules = ("-posts",)
__tablename__ = "user"
id = db.Column(db.String(100), primary_key=True, default=shortuuid.uuid)
username = db.Column(db.String(50), nullable=False)
class PostModel(db.Model, SerializerMixin):
__tablename__ = "post"
id = db.Column(db.String(100), primary_key=True, default=shortuuid.uuid)
title = db.Column(db.String(100), nullable=False)
content = db.Column(db.Text, nullable=False)
author_id = db.Column(db.String(100), db.ForeignKey("user.id"))
author = db.relationship("UserModel", backref="posts")
在序列化PostModel的時候,也會自動遞歸序列化author,并且author的值有id和username兩個字段。這里有個細節(jié)需要注意,就是UserModel必須要排除posts。因為PostModel中的author字段,通過backref給UserModel綁定了一個posts字段,如果不排除posts,那么在序列化author的時候,又會序列化posts,造成循環(huán)遞歸序列化。
五、高級用法:
基本上學(xué)會以上用法后,99%的場景都沒有問題了。如果你在使用sqlalchemy_serializer還有其他業(yè)務(wù)需求,比如格式化日期的輸出、字段扁平化等,那么可以再仔細閱讀一下sqlalchemy_serializer的官方文檔:官方文檔
項目中引用文章來源:http://www.zghlxwxcb.cn/news/detail-592850.html
將登錄后數(shù)據(jù)序列化返回
序列化后的數(shù)據(jù),此時看到的跟該用戶相關(guān)的評論,帖子也序列化了,這就會循環(huán)序列化
可以設(shè)置僅序列化的字段文章來源地址http://www.zghlxwxcb.cn/news/detail-592850.html
到了這里,關(guān)于Flask SQLAlchemy_Serializer ORM模型序列化的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!