建立自定義類型有以下三種方式:
- 繼承 Filed 類,根據需求進行實作
- 使用 Method 字段
- 使用 Function 字段
繼承 FIled 類
首先我們介紹第一種方法,書寫
marshmallow.fields.Field
的子類,然後實作它的
_serialize
和
_deserialize
方法。
from marshmallow import fields, ValidationError
class PinCode(fields.Field):
"""Field that serializes to a string of numbers and deserializes
to a list of numbers.
"""
def _serialize(self, value, attr, obj, **kwargs):
if value is None:
return ""
return "".join(str(d) for d in value)
def _deserialize(self, value, attr, data, **kwargs):
try:
return [int(c) for c in value]
except ValueError as error:
raise ValidationError("Pin codes must contain only digits.") from error
class UserSchema(Schema):
name = fields.String()
email = fields.String()
created_at = fields.DateTime()
pin_code = PinCode()
Methods 字段
被 Method 修飾的字段将會通過指定的方法來對資料進行序列化,并且該方法必須接收一個參數用來表示傳入的帶序列化對象。
Methods 修飾的字段必須接收一個字元串
class UserSchema(Schema):
name = fields.String()
email = fields.String()
created_at = fields.DateTime()
since_created = fields.Method("get_days_since_created")
def get_days_since_created(self, obj):
return dt.datetime.now().day - obj.created_at.day
Methods 字段的反序列化
files.Methods() 可以接收
deserialize 參數
,用來指定反序列化時的邏輯。
class UserSchema(Schema):
# `Method` takes a method name (str), Function takes a callable
balance = fields.Method("get_balance",
deserialize="load_balance")
def get_balance(self, obj):
return obj.income - obj.debt
def load_balance(self, value):
return float(value)
schema = UserSchema()
result = schema.load({"balance": "100.00"})
result["balance"] # => 100.0
Function 字段
Function 修飾的字段也能夠對資料進行序列化,類似于 Methods,同樣是隻接收一個參數,但是接收的不再是一個字元串,而是一個可調用的方法。
class UserSchema(Schema):
name = fields.String()
email = fields.String()
created_at = fields.DateTime()
uppername = fields.Function(lambda obj: obj.name.upper())
Function 的反序列化
參考 Methods 的實作方式
通過 context 來進行管理
對于一個 schema,我們可以在指定的 Schema 執行個體對象的 上下文當中添加額外的内容,并通過 context 來對反序列化内容進行自定義:
class UserSchema(Schema):
name = fields.String()
# Function fields optionally receive context argument
is_author = fields.Function(lambda user, context: user == context["blog"].author)
likes_bikes = fields.Method("writes_about_bikes")
def writes_about_bikes(self, user):
return "bicycle" in self.context["blog"].title.lower()
schema = UserSchema()
user = User("Freddie Mercury", "[email protected]")
blog = Blog("Bicycle Blog", author=user)
schema.context = {"blog": blog}
result = schema.dump(user)
result["is_author"] # => True
result["likes_bikes"] # => True
自定義字段的錯誤消息
針對序列化對應的字段類型,我們也可以對自定義的類型進行錯誤消息的書寫:
from marshmallow import fields
class MyDate(fields.Date):
default_error_messages = {
"invalid": "Please provide a valid date."
}
例如上面的 MyDate 資料類型,我們可以在類屬性當中對其錯誤消息進行指定。
當然,我們也可以在 fileds 當中的資料類型執行個體化的時候進行指定:
from marshmallow import Schema, fields
class UserSchema(Schema):
name = fields.Str(
required=True, error_messages={
"required": "Please provide a name."
}
)
參考文檔:Custom Fields — marshmallow 3.12.1 documentation