博主:👍不许代码码上红
欢迎:🐋点赞、收藏、关注、评论。
一、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”)