Marshmallow及ORM小结

前记

自己总结使用的,有错误之处欢迎之处。
觉得没用请直接退出,不必浪费您的时间私信骂没用。

  • 一句话总结:
    • ORM可以实现用python语句操作数据库,而不用写相应的sql语句。
    • marshmallow可以将对应的数据(json形式)转换为python自己的数据类型从而存入生成的数据库中。
      或者将数据库的内容转换为对应的json格式传输到前端。

marshmallow是什么?

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

ORM是什么?

  • ORM(Object Relational Mapping)
  • 对象——关系(数据库)之间的映射
    • 可以通过简易的ORM框架的API进行数据库的操作。
    • 即通过在python中操作对象从而实现对数据库进行操作。
    • 定义一个对象,那就对应着一张表,这个对象的实例,就对应着表中的一条记录
  • 作用
    • 关系型数据库对象之间作一个映射,这样,我们在具体的操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只要像平时操作对象一样操作它就可以了 。
  • 说人话:通过ORM可以将写成的python代码自动转换成对应的sql语句并自动添加对应的字段。(参照对应的函数写相应的python代码)
  • 写相应的python语句创造model的对象,然后第一次创建时会自动生成对应的SQL语句及字段(后续需要手动修改生成的内容)。
  • 可以参考Object Relational Mapping(ORM)python_flask_ORM用法写的很详细。

marshmallow中的序列化与反序列化

  • 序列化:将数据对象转化为可存储或可传输的数据类型(例如json)
    • dump()/dumps()
  • 反序列化:将可存储或可传输的数据类型转化为数据对象
    • load()/loads()

创建一个object作为基础

import datetime as dt


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

中间载体shema

  • 数据结构之间的相互转换,需要有一个中间载体来实现,这个载体就是Schema类。
  • 因此需要创建一个继承自Schema的UserSchema类,有两种方式创建。
  • UserSchema类可以将User的属性名映射到Field对象。
# 定义一个类继承Schema
from marshmallow import Schema, fields


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

# 使用Schema的from_dict()方法
from marshmallow import Schema, fields


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

简述Serializing(序列化对象)

  • 即把自定义的对象转换为Python内置的对象(dict, str, list)。
  • dump()方法:可以将一个object(对象)转换为一个dict(字典),示例如下:
user = User(name="TTY", email="tty@python.org")
schema = UserSchema()
res = schema.dump(user)
print(res)
# {'email': 'tty@python.org', 'name': 'TTY', 'created_time': '2019-08-05T14:43:51.168241+00:00'}
  • dumps()方法:可以将一个object(对象)转换为一个str(json格式字符串),示例如下:
res2 = schema.dumps(user)
print(res2)
# '{"name": "TTY", "created_time": "2019-08-05T14:46:07.111755+00:00", "email": "tty@python.org"}'

序列化相关参数

  • attribute
    schema默认会序列化传入对象和自身定义的fields相同的属性, 然而你也会有需求使用不同的fields和属性名。
    在这种情况下, 你需要明确定义这个fields将从什么属性名取值明确定义这个fields将从什么属性名取值。
    下面代码中:UserSchema中的full_name,email_address,created_at分别从User对象的name,email,created_time属性取值。
class UserSchema(Schema):
    full_name = fields.String(attribute="name")
    email_address = fields.Email(attribute="email")
    created_at = fields.DateTime(attribute="created_time")
  • dump_only——等同于只读字段。
    # created_at is "read-only"
    created_at = fields.DateTime(dump_only=True)
  • default——输入值缺失default指定默认值
class UserSchema(Schema):
    birthdate = fields.DateTime(default=dt.datetime(2020, 9, 9))

简述Deserializing(反序列化)

  • 反序列化是将Python内置的对象转换为自定义的对象
  • load()方法:它将输入的字典格式数据转换成应用层数据结构。他也能起到验证输入的字典格式数据的作用。默认情况下,load()方法返回一个字典,当输入的数据的值不匹配字段类型时,抛出 ValidationError 异常。
schema = UserSchema()
res = schema.load(user_data)
print(res)
# {'email': 'tty2@python.org', 'created_time': datetime.datetime(2019, 8, 5, 14, 46, 7), 'name': 'tty2'}
  • loads()方法:可将json字符串转换为dict
user_json = '{ "created_at": "2014-08-11T05:26:03.869245", "email": "ken@yahoo.com", "name": "Ken" }'
schema = UserSchema()
j2d = schema.loads(user_json)    # 此处传入的是一个json字符串,返回的一个字典
print('j2d:', type(j2d), j2d)

# 输出结果如下:
j2d: <class 'dict'> {'created_at': datetime.datetime(2021, 2, 26, 14, 46, 15, 787833), 'name': 'Monty', 'email': 'monty@python.org'}

反序列化参数

  • load_from
    Schema默认反序列化传入字典和输出字典中相同的字段名。
    如果你觉得数据不匹配你的schema, 可以传入load_from参数指定需要增加load的字段名。
    (原字段名也能load, 且优先load原字段名)
class UserSchema(Schema):
    full_name = fields.String(load_from="name")
    email_address = fields.Email(load_from="email")
    created_at = fields.DateTime(load_from="created_time")
  • load_only——等同于只写字段。
    # password is "write-only"
    password = fields.Str(load_only=True)
  • missing——输入值缺失用missing指定默认值。
class UserSchema(Schema):
    id = fields.UUID(missing=uuid.uuid1)

通用参数

  • many = True——处理多个对象的集合

    • 多个对象的集合如果是可迭代的,那么也可以直接对这个集合进行序列化或者反序列化。在实例化Scheme类时设置参数many=True
    • 也可以不在实例化类的时候设置,而在调用dump()方法的时候传入这个参数。
user1 = User(name="tty1", email="tty1@python.org")
user2 = User(name="tty2", email="tty2@python.org")
users = [user1, user2]

# 第一种方法
schema = UserSchema(many=True)
res = schema.dump(users)

# 第二种方法
# schema = UserSchema()
# res = schema.dump(users, many=True)

print(res)
# [{'created_time': '2019-08-05T15:09:19.781325+00:00', 'email': 'tty1@python.org', 'name': 'tty1'},
#  {'created_time': '2019-08-05T15:09:19.781325+00:00', 'email': 'tty2@python.org', 'name': 'tty2'}]
  • data_key——让key同时满足序列化与反序列化的方法
class UserSchema(Schema):
    full_name = fields.String(data_key="name")
    email_address = fields.Email(data_key="email")
    created_at = fields.DateTime(data_key="created_time")

必填字段校验——required=True

  • 必填字段的校验,可通过传入关键字参数required=True ,可以自定义缺失字段时抛出的异常信息:设置参数error_messages的值,示例:
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:
    print(err.messages)
    # {'age': ['Age is required.'],
    # 'city': {'code': 400, 'message': 'City required'},
    # 'name': ['Missing data for required field.']}

忽略部分字段——partial

  • 使用required之后我们还是可以在传入数据的时候忽略这个必填字段。
  • 只想校验部分的字段,可以通过传递partial参数来指定需要校验的字段,示例:
class UserSchema(Schema):
    name = fields.String(required=True)
    age = fields.Integer(required=True)

# 方法一:在load()方法设置partial参数的值(元组),表时忽略那些字段。
schema = UserSchema()
res = schema.load({"age": 42}, partial=("name",))
print(res)
# {'age': 42}

# 方法二:直接设置partial=True
schema = UserSchema()
res = schema.load({"age": 42}, partial=True)
print(res)
# {'age': 42}

参考文献

什么是ORM
Object Relational Mapping(ORM)
python_flask_ORM——用法很详细
python之Marshmallow
Marshmallow快速上手及参数校验

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值