mongoengine_marshmallow库的使用


文章目录

  • mongoengine_marshmallow库的使用
  • 一. 安装
  • 二. marshmallow用法
  • 1. 序列化(dump)
  • 2.反序列化(load)
  • 3. 更新操作(update)
  • 4. 字段验证
  • 5. Meta元类常用属性
  • 6.常用字段类型
  • 7.字段参数



在Django中有Serializer模块将Model字段序列化输出,Flask+sqlalchemy也可以解决关系型数据库的ORM序列化,那么如果用Flask+MongoEngine该如何选择呢

在搜索了许久之后, 找到了marshmallow库, 它本身不是针对ORM的,包装之后可以为mongoengine所用,达到最基本的功能序列化,反序列化,字段验证

一. 安装

# requirements.txt
Flask==1.0.2
flask-mongoengine==0.9.5
marshmallow_mongoengine
marshmallow==2.13.6

执行

pip install -r requirements.txt

二. marshmallow用法

dump - 序列化
load - 反序列化
update - 更新
validate - 字段验证, 可自定义

写个模型和序列化类

from marshmallow_mongoengine import ModelSchema, fields
# model
class User(db.Document):
    name = db.StringField()
    age = db.IntField()
    
# serializer
class UserSchema(ModelSchema):
  name = fields.String()
  age = fields.Int()
  class Meta:
    model = User

1. 序列化(dump)

>>> a = User(name="我是第一个").save()
>>> a
<User: User object>
>>> dump_data = UserSchema().dump(a)
>>> dump_data
MarshalResult(data={'id': '5cda5e43fe985e28c8e0c3b6', 'name': '我是第一个'}, errors={})
# 使用dump_data.data就可以获取到序列化后的值

可以看到,序列化后的值缺少了age字段, 因为age字段没有值,那么要怎么返回age字段呢?

只需要在UserSchema类下的Meta元类添加一条属性model_skip_values = ()

# UserSchema改为
class UserSchema(ModelSchema):
  name = fields.String()
  age = fields.Int()
  class Meta:
    model_skip_values = ()
    model = User

再来看结果

>>> UserSchema().dump(a)
MarshalResult(data={'id': '5cda5e43fe985e28c8e0c3b6', 'name': '我是第一个', 'age': None}, errors={})

2.反序列化(load)

data = {"name":"哈哈", "age":11}

load_data = UserSchema().load(data)
>>> UnmarshalResult(data=<User: User object>, errors={})

3. 更新操作(update)

第一次尝试


处理报错

检查发现安装的marshmallow版本为最新的3.0+,在issue中找到了解决方案,安装2.13.6版本的marshmallow

第二次尝试


只修改了status字段,可以看出这样并没有什么变化,因为没有做保存操作

第三次尝试

结果检测

update方法测试成功

4. 字段验证

>>> data = {"name": 123}
>>> schema = UserSchema()
>>> schema.validate(data)
{'name': ['Not a valid string.']}

自定义逻辑

class UserSchema(ModelSchema):
  ...
    
  def validate(self, data, *args, **kwargs):
        # 兼容前端age传null
        if 'age' in data and data['age'] is None:
            data['age'] = ''
        return super().validate(data, *args, **kwargs)

5. Meta元类常用属性

class Meta:
  model = User								# 指定model
  model_skip_values = ()			# 指定不展示的字段值
  exclude = ("id",)						# 排除字段
  fields = ("name", "age")		# 展示字段,不写该属性默认为model所有字段

6.常用字段类型

from marshmallow_mongoengine import ModelSchema, fields

# serializer
class UserSchema(ModelSchema):
  name = fields.String()							# 字符
  age = fields.Int()									# int型
  is_admin = fields.Boolean()					# 布尔类型
  book = fields.Nested(BookSchema, many=True)		# 引用型,many=True则为list
  create_by = fields.Function(lambda obj: obj.create_by.name)		# 自定义函数值
  family = fields.Method("get_family")		# 指定方法
  
  def get_family(self, obj):
    # 下面的只是个示例,意思是你可以通过自定义方法返回值给该字段
    return FamilySchema(fields=("nickname", "id")).dump(obj.family, many=True).data

7.字段参数

  • required:必选,缺省会触发validate校验返回错误 xx is required fields
  • load_only: 仅反序列化时使用, 避免同一个序列化类使用报错
  • dump_only: 仅序列化时使用
  • attribute: 将数据库字段以你指定的名称展示
_id = fields.String(attribute="id")
  • default: 序列化时值不存在默认展示
  • format: 格式化输出
create_at = fields.DateTime(format='%Y-%m-%d %H:%M:%S')

参考文档:

marshmallow

mongoengine_mashmallow