Flask SQLAlchemy_Serializer ORM模型序列化

在前后端分离项目中,经常需要把ORM模型转化为字典,再将字典转化为JSON格式的字符串。在遇到sqlalchemy_serializer之前,我都是通过类似Java中的反射原理,获取当前ORM模型的所有字段,然后写一个to_dict方法来将字段以及他的值封装成字典。大概的代码如下所示:

javascript 复制代码
def to_dict(self):
  return {c.name: str(getattr(self, c.name)) for c in self.__table__.columns}

这种做法虽然一定程度上方便了开发,但也是带着枷锁跳舞,存在以下几个弊端:

  1. 无法优雅的排除不需要序列化的字段。

  2. 无法优雅的序列化多表之间的关系。

直到后来我遇到了sqlalchemy_serializer,泪流满面,这不就是我苦苦寻找的ORM模型序列化库吗?使用他序列化ORM模型,让我带你看看有多爽!

一、安装:

sqlalchemy-serializer已经上架PyPi,因此通过pip命令即可安装:

javascript 复制代码
 pip install SQLAlchemy-serializer

二、基本使用:

如果想要让某个ORM模型能被序列化,那么只需要在定义模型的时候,让他继承自sqlalchemy_serializer.SerializerMixin即可,示例代码如下:

javascript 复制代码
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模型序列化成字典:

javascript 复制代码
user = UserModel.query.filter(...).one()
user_dict = user.to_dict()

上述代码中将把UsrModel中所有字段都序列化成字典。

三、排除字段:

模型中有的字段不需要被序列化,比如用户的密码,那么这时候可以通过设置rules参数,或者only参数来指定序列化规则。比如排除password,那么可以通过如下代码方式实现:

javascript 复制代码
user = UserModel.query.filter(...).one()
user_dict = user.to_dict(rules=('-password',))

上述代码中在调用to_dict方法的时候,传递了rules参数,并且设置了-password,其中的-号代表排除的意思,意思是不要序列化password。如果在绝大部分场景下都不需要某些字段,可以把这个规则写在模型定义中,这样所有序列化的时候,都会遵循这个序列化规则。比如:

javascript 复制代码
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)

如果需要排除的字段太多了,我们可以通过设置serialize_only属性来标记仅仅序列化某些字段。比如:

javascript 复制代码
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会默认序列化定义好关系的模型,比如有UserModel和PostModel两个模型:

javascript 复制代码
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两个字段。这里有个细节需要注意,就是UserModel必须要排除posts。因为PostModel中的author字段,通过backref给UserModel绑定了一个posts字段,如果不排除posts,那么在序列化author的时候,又会序列化posts,造成循环递归序列化。

五、高级用法:

基本上学会以上用法后,99%的场景都没有问题了。如果你在使用sqlalchemy_serializer还有其他业务需求,比如格式化日期的输出、字段扁平化等,那么可以再仔细阅读一下sqlalchemy_serializer的官方文档:官方文档

项目中引用

将登录后数据序列化返回

序列化后的数据,此时看到的跟该用户相关的评论,帖子也序列化了,这就会循环序列化

可以设置仅序列化的字段

相关推荐
封步宇AIGC21 分钟前
量化交易系统开发-实时行情自动化交易-Okex K线数据
人工智能·python·机器学习·数据挖掘
哎呦没21 分钟前
SpringBoot框架下的资产管理自动化
java·spring boot·后端
封步宇AIGC23 分钟前
量化交易系统开发-实时行情自动化交易-Okex交易数据
人工智能·python·机器学习·数据挖掘
2401_8576009524 分钟前
SpringBoot框架的企业资产管理自动化
spring boot·后端·自动化
小爬虫程序猿25 分钟前
如何利用Python解析API返回的数据结构?
数据结构·数据库·python
波点兔28 分钟前
【部署glm4】属性找不到、参数错误问题解决(思路:修改模型包版本)
人工智能·python·机器学习·本地部署大模型·chatglm4
一点媛艺3 小时前
Kotlin函数由易到难
开发语言·python·kotlin
魔道不误砍柴功4 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
NiNg_1_2344 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
_.Switch5 小时前
高级Python自动化运维:容器安全与网络策略的深度解析
运维·网络·python·安全·自动化·devops