Marshmallow 快速文档

本文主要对marshmallow的文档进行整理,并记录在学习Marshmallow文档时碰到的一些问题和解决方法
原文链接:https://marshmallow.readthedocs.io/en/stable/quickstart.html

Todo:

  • 添加validation相关的内容
  • 将内容按照接口重新排序
  • 添加ordering, implicit field creation, nested schemas, custom field, extending schemas相关的内容
  • 纠正翻译

正文

1. 声明schema

首先创建一个简单的User类,声明了构造方法和覆写__repr__方法用于打印对象

import datetime as dt
class User:
    def __init__(self, name, email):
        self.name = name
        self.email = email
        self.created_at = dt.datetime.now()

    def __repr__(self):
        return "<User(name={self.name!r})>".format(self=self)

然后创建一个继承Schema的UserSchema类,里面生成name,email,create_at变量,映射属性名到Field对象

from marshmallow import Schema, fields

class UserSchema(Schema):
    name = fields.Str()
    email = fields.Email()
    created_at = fields.DateTime()

也可以使用Schema.from_dict()通过传入dict来创建Schema。比较有用的应用场景是在运行中生成Schema

UserSchema = Schema.from_dict(
	{
	    "name": fields.Str(), 
	    "email": fields.Email(), 
	    "created_at": fields.DateTime()}
	)

2. 序列化对象 – dumping

使用dump、dumps可以序列化对象。dump返回格式化好的数据,dumps返回json String

from pprint import pprint

user = User(name="Monty", email="monty@python.org")
schema = UserSchema()
result = schema.dump(user)
pprint(result)
# {"name": "Monty",
#  "email": "monty@python.org",
#  "created_at": "2014-08-17T14:54:16.049594+00:00"}

2.1 过滤输出 – only

使用only,传入tuple或者数组,可以指定输出的fields

summary_schema = UserSchema(only=("name", "email"))
summary_schema.dump(user)
# {"name": "Monty", "email": "monty@python.org"}

3. 反序列化 – load

dump反过来就是load,load会验证并反序列化一个字典 为 应用级别的数据结构。直接使用load,会将dict中的value转换成对应field定义的对象。

from pprint import pprint

user_data = {
    "created_at": "2014-08-11T05:26:03.869245",
    "email": "ken@yahoo.com",
    "name": "Ken",
}
schema = UserSchema()
result = schema.load(user_data)
pprint(result)
# {'name': 'Ken',
#  'email': 'ken@yahoo.com',
#  'created_at': datetime.datetime(2014, 8, 11, 5, 26, 3, 869245)},

如果想将dict整体转换为对象,需要在Schema 中声明一个方法并用@post_load装饰。下面的例子就是将dict转换成了User对象

from marshmallow import Schema, fields, post_load

class UserSchema(Schema):
    name = fields.Str()
    email = fields.Email()
    created_at = fields.DateTime()

    @post_load
    def make_user(self, data, **kwargs):
        return User(**data)
        
user_data = {"name": "Ronnie", "email": "ronnie@stones.com"}
schema = UserSchema()
result = schema.load(user_data)
print(result)  # => <User(name='Ronnie')>

4. 处理对象集合(多个对象)

在创建Schema的时候,传入(many=True),让Schema可以处理多个对象

user1 = User(name="Mick", email="mick@stones.com")
user2 = User(name="Keith", email="keith@stones.com")
users = [user1, user2]
schema = UserSchema(many=True)
result = schema.dump(users)  # OR UserSchema().dump(users, many=True)
pprint(result)
# [{'name': u'Mick',
#   'email': u'mick@stones.com',
#   'created_at': '2014-08-17T14:58:57.600623+00:00'}
#  {'name': u'Keith',
#   'email': u'keith@stones.com',
#   'created_at': '2014-08-17T14:58:57.600623+00:00'}]

5. 必须值 required

在field中传入required,说明这个值不可或缺。如果缺少值的话,会报错。可以通过 error_messages={“required”: {“message”: “City required”, “code”: 400}} 来自定义错误返回的消息和错误码

from pprint import pprint

from marshmallow import Schema, fields, ValidationError

class UserSchema(Schema):
    name = fields.String(required=True)
    age = fields.Integer(required=True, error_messages={"required": "Age is required."})
    city = fields.String(
        required=True,
        error_messages={"required": {"message": "City required", "code": 400}},
    )
    email = fields.Email()

try:
    result = UserSchema().load({"email": "foo@bar.com"})
except ValidationError as err:
    pprint(err.messages)
    # {'age': ['Age is required.'],
    # 'city': {'code': 400, 'message': 'City required'},
    # 'name': ['Missing data for required field.']}

当一个schema用在不同地方时,required的值不同的话,通过load时传入partial=(“需要忽略的”),可以忽略required要求的字段值。
直接传入partial=True可以忽略所有的required

class UserSchema(Schema):
    name = fields.String(required=True)
    age = fields.Integer(required=True)

result = UserSchema().load({"age": 42}, partial=("name",)) #跳过name
# OR UserSchema(partial=('name',)).load({'age': 42}) 
print(result)  # => {'age': 42}

result = UserSchema().load({"age": 42}, partial=True) #跳过所有
# OR UserSchema(partial=True).load({'age': 42})
print(result)  # => {'age': 42}

5. 声明默认值

通过load_default和dump_default,声明默认值

class UserSchema(Schema):
    id = fields.UUID(load_default=uuid.uuid1)
    birthdate = fields.DateTime(dump_default=dt.datetime(2017, 9, 29))

UserSchema().load({})
# {'id': UUID('337d946c-32cd-11e8-b475-0022192ed31b')}
UserSchema().dump({})
# {'birthdate': '2017-09-29T00:00:00+00:00'}

6. 只读和只写

在fields.str()中传入load_only=True是只写,dump_only=True是只读

class UserSchema(Schema):
    name = fields.Str()
    # password is "write-only"
    password = fields.Str(load_only=True)
    # created_at is "read-only"
    created_at = fields.DateTime(dump_only=True)

7. 自定义key

如果输入和输出的变量名不同,需要使用data_key=""自定义key的名称

class UserSchema(Schema):
    name = fields.String()
    email = fields.Email(data_key="emailAddress")

s = UserSchema()

data = {"name": "Mike", "email": "foo@bar.com"}
result = s.dump(data)
# {'name': u'Mike',
# 'emailAddress': 'foo@bar.com'}

data = {"name": "Mike", "emailAddress": "foo@bar.com"}
result = s.load(data)
# {'name': u'Mike',
# 'email': 'foo@bar.com'}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值