• 【Python】Marshmallow:Python中的“棉花糖”


    在这里插入图片描述

    博主:👍不许代码码上红
    欢迎:🐋点赞、收藏、关注、评论。

    一、Marshmallow简介

    1.1、基础概念

    第一点
    marshmallow是一个用来将复杂的orm对象与python原生数据类型之间相互转换的库,简而言之,就是实现object -> dict,objects -> list, string -> dict 和string -> list。

    第二点
    Flask-Marshmallow包含用于集成的有用附加功能Flask-SQLAlchemy和 marshmallow-sqlalchemy。要启用SQLAlchemy集成,请确保同时安装了Flask-SQLAlchemy和marshmallow-sqlalchemy。

    二、序列化

    序列化:序列化的意思是将数据对象转化为可存储或可传输的数据类型
    反序列化:将可存储或可传输的数据类型转化为数据对象

    2.1、User类

    要进行序列化或反序列化,首先我们需要一个用来操作的object,这里我们先定义一个类

    class User:
        def __init__(self, name, email):
            self.name = name
            self.email = email
            self.created_time = dt.datetime.now()
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    2.2、UserSchema类

    要对一个类或者一个json数据实现相互转换(即序列化和反序列化), 需要一个中间载体,这个载体就是Schema,另外Schema还可以用来做数据验证。

    class UserSchema(Schema):
        name = fields.String()
        email = fields.Email()
        created_time = fields.DateTime()
    
    • 1
    • 2
    • 3
    • 4

    2.3、Serializing(序列化)

    dump():scheme的dump()方法来序列化对象,返回的是dict格式的数据

    dumps():schema的dumps()方法序列化对象,返回的是json编码格式的字符串

    user = User("小明","123456")
    schema = UserSchema()
    res = schema.dump(user)
    res2 = schema.dumps(user)
    print(type(res))
    print(res)
    print(type(res2))
    print(res2)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.4、运行

    在这里插入图片描述

    2.5、过滤输出

    当不需要输出所有的字段时,可以在实例化Scheme时,声明only参数,来指定输出

    summary_schema = UserSchema(only={"name","email"})
    res = summary_schema.dump(user)
    print(res)
    
    • 1
    • 2
    • 3

    在这里插入图片描述

    三、反序列化

    每次调用load()方法时, 会按照make_user的逻辑, 返回一个User类对象
    注意:def make_user(self, data,**kwargs)
    代码

    import datetime as dt
    
    from marshmallow import Schema, fields, post_load
    
    
    class User:
        def __init__(self, name, email):
            self.name = name
            self.email = email
            self.created_time = dt.datetime.now()
    
    class UserSchema(Schema):
        name = fields.String()
        email = fields.Email()
        created_time = fields.DateTime()
    #dict->object()
        @post_load
        def make_user(self, data,**kwargs):
            return User(**data)
    
    user_data = {
        "name": "lhh",
        "email": "2432783449@qq.com",
        # "created_time": "2022-09-08T21:34:34.443495"
    }
    
    schema = UserSchema()
    res = schema.load(user_data)
    print(res)
    user = res
    print("name: {}    email: {}".format(user.name, user.email))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    在这里插入图片描述

    四、验证数据

    4.1、Validation

    当不合法的数据通过Schema.load()或者Schema.loads()时,会抛出一个 ValidationError 异常。ValidationError.messages属性有验证错误信息,验证通过的数据在 ValidationError.valid_data 属性中 我们捕获这个异常,然后做异常处理。
    创建一个validation.py,代码如下

    from marshmallow import Schema,fields,ValidationError
    
    
    class UserSchema(Schema):
        name = fields.String()
        email = fields.Email()
        created_time = fields.DateTime()
    
    try:
        res = UserSchema().load({"name":"王小明","email":"123"})
    
    except ValidationError as e:
        print(f"错误信息:{e.messages}  合法数据:{e.valid_data}")
    
    '''
        当验证一个数据集合的时候,返回的错误信息会以 错误序号-错误信息 的键值对形式保存在errors中
    '''
    user_data = [
        {'email': '123456@qq.com', 'name': '王小明'},
        {'email': '123', 'name': '王小明'},
        {'name': '王小明'},
        {'email': '123@qq.com'},
    ]
    
    
    try:
        schema = UserSchema(many=True)
        res = schema.load(user_data)
        print(res)
    except ValidationError as e:
        print("错误信息:{}   合法数据:{}".format(e.messages, e.valid_data))
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    在这里插入图片描述

    4.2、自定义验证错误提示

    from marshmallow import Schema,fields,ValidationError
    
    
    class UserSchema(Schema):
        name = fields.String(required=True, validate=lambda s:len(s) < 6)
        email = fields.Email()
        created_time = fields.DateTime()
    
    user_data = {"name":"","email":"123@qq.com"}
    try:
        res = UserSchema().load(user_data)
    except ValidationError as e:
        print(e.messages)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    当名字长度小于6时无报错信息
    user_data = {“name”:“王小明”,“email”:“123@qq.com”}

    在这里插入图片描述
    当名字长度大于6时
    user_data = {“name”:“王小明爱看电影”,“email”:“123@qq.com”}

    在这里插入图片描述

    4.3、自定义验证错误提示原因

    user_data = {“name”:“王”,“email”:“123@qq.com”}

    from marshmallow import Schema,fields,ValidationError
    
    def validate_name(name):
        if len(name) <=2:
            raise ValidationError("name长度必须大于2位")
        if len(name) >= 6:
            raise ValidationError("name长度不能大于6位")
    
    
    
    
    class UserSchema(Schema):
        name = fields.String(required=True, validate=validate_name)
        email = fields.Email()
        created_time = fields.DateTime()
    
    user_data = {"name":"","email":"123@qq.com"}
    try:
        res = UserSchema().load(user_data)
    except ValidationError as e:
        print(e.messages)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述

    4.4、将验证函数写在Schema中变成验证方法

     @validates("name")
        def validate_name(self, value):
            if len(value) <= 2:
                raise ValidationError("name长度必须大于2位")
            if len(value) >= 6:
                raise ValidationError("name长度不能大于6位")
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    from marshmallow import Schema, fields, ValidationError, validates
    
    
    class UserSchema(Schema):
        name = fields.String(required=True)
        email = fields.Email()
        created_time = fields.DateTime()
    
        @validates("name")
        def validate_name(self, value):
            if len(value) <= 2:
                raise ValidationError("name长度必须大于2位")
            if len(value) >= 6:
                raise ValidationError("name长度不能大于6位")
    
    
    user_data = {"name":"王","email":"123@qq.com"}
    try:
        res = UserSchema().load(user_data)
    except ValidationError as e:
        print(e.messages)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    在这里插入图片描述

    五、排序

    对于某些用例,维护序列化输出的字段顺序可能很有用。要启用排序,请将ordered选项设置为true。这将指示marshmallow将数据序列化到collections.OrderedDict

    from collections import OrderedDict
    import datetime as dt
    from marshmallow import fields,Schema
    
    class User:
        def __init__(self, name, email):
            self.name = name
            self.email = email
            self.created_time = dt.datetime.now()
    
    class UserSchema(Schema):
        # uppername = fields.Function(lambda obj: obj.name.upper())
    
        class Meta:
            fields = ("email","name", "created_time")
            ordered = True
    
    
    user = User("王小明", "123@qq.com")
    schema = UserSchema()
    res = schema.dump(user)
    print(isinstance(res,OrderedDict))  # 判断变量类型
    # True
    print(res)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    顺序:fields = (“email”,“name”, “created_time”)
    在这里插入图片描述

  • 相关阅读:
    陪你去看 Lodash.js 起步
    K8S常见的持久化(存储)方案用法详解
    java计算机毕业设计在线招生系统源代码+系统+数据库+lw文档
    Matlab:在键入时检查语法
    记一次 Visual Studio 2022 卡死分析
    机器学习(三)之监督学习2
    用于可扩展、可重用和优雅的代码的Python工厂
    金仓数据库KingbaseES安全指南--6.5. LDAP身份验证
    C#基础巩固与进阶(定时语音播报+PDF水印+分片上传+EF6框架)
    SQL注入漏洞及五大手法
  • 原文地址:https://blog.csdn.net/qq_45801904/article/details/126766011