概要
marshmallow の load と dump 時に自動的にコールされる pre_ post_ 系のデコレータの処理の挙動を確認してみました
環境
- macOS 11.5.2
- Python 3.8.3
- marshmallow 3.13.0
インストール
- pipenv install marshmallow
サンプルコード
from marshmallow import (
Schema, pre_load, post_load, post_dump, fields
)
class User():
def __init__(self, email, age):
self.email = email
self.age = age
class UserSchema(Schema):
email = fields.Str(required=True)
age = fields.Integer(required=True)
@pre_load(pass_many=True)
def remove_envelope(self, data, many, **kwargs):
# ルート要素 (result or results) を data から取得する
# 取得した data[namespace] は post_load で item に格納される
namespace = 'results' if many else 'result'
return data[namespace]
@post_load
def lowerstrip_email(self, item, many, **kwargs):
# 各 item に格納されている値を加工する場合はこちらを使います
# many=True の場合は自動的に複数回コールされます
item['email'] = item['email'].lower().strip()
return item
@post_dump(pass_many=True)
def add_envelope(self, data, many, **kwargs):
# many=True の場合は results をルートキーとする dict を返却します
namespace = 'results' if many else 'result'
return {namespace: data}
schema = UserSchema()
result = schema.load({"result": {"age": "1", "email": "test1@mail"}})
print(result)
result = schema.load({"results": [{"age": "2", "email": "test2@mail"}, {"age": "3", "email": "test3@mail"}]}, many=True)
print(result)
user4 = User("test4@mail", 4)
result = schema.dump(user4)
print(result)
user5 = User("test5@mail", 5)
user6 = User("test6@mail", 6)
result = schema.dump([user5, user6], many=True)
print(result)
解説、挙動の確認
schema.load がコールされた場合には pre_load と post_load が自動的にコールされます
schema.dump がコールされた場合は pre_dump と post_dump が自動的にコールされます
load は dict -> dict の変換します
指定したキーの値配下の情報を取得しています
dump は class -> dict の変換をします
こちらのほうがよく使う手法になるかなと思います
pre_ ではデータの加工は行わず必要なデータの取得などを行います
post_ 側でデータを加工するので post_ 側に渡すデータを必ず return する必要があります
many=True の場合は post_ が自動的に複数回コールされて各要素分だけ処理されます
最後に
- pre_ はデータの加工をする対象の抽出
- post_ でデータの加工をする
というのが主な使い方になるかなと思います
0 件のコメント:
コメントを投稿