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

发布于:2022-12-22 ⋅ 阅读:(459) ⋅ 点赞:(0)

在这里插入图片描述

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

一、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()

在这里插入图片描述

2.2、UserSchema类

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

class UserSchema(Schema):
    name = fields.String()
    email = fields.Email()
    created_time = fields.DateTime()

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)

2.4、运行

在这里插入图片描述

2.5、过滤输出

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

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

在这里插入图片描述

三、反序列化

每次调用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))

在这里插入图片描述

四、验证数据

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))

在这里插入图片描述

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)

当名字长度小于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)

在这里插入图片描述

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位")

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)

在这里插入图片描述

五、排序

对于某些用例,维护序列化输出的字段顺序可能很有用。要启用排序,请将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)

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

本文含有隐藏内容,请 开通VIP 后查看