天天看點

marshmallow——自定義類型繼承 FIled 類Methods 字段Function 字段通過 context 來進行管理自定義字段的錯誤消息

建立自定義類型有以下三種方式:

  • 繼承 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