Custom class Meta options#

class Meta options are a way to configure and modify a Schema's behavior. See marshmallow.Schema.Meta for a listing of available options.

You can add custom class Meta options by subclassing marshmallow.SchemaOpts.

Example: Enveloping, revisited#

Let’s build upon the previous enveloping implementation above for adding an envelope to serialized output. This time, we will allow the envelope key to be customizable with class Meta options.

# Example outputs
{
    'user': {
        'name': 'Keith',
        'email': 'keith@stones.com'
    }
}
# List output
{
    'users': [{'name': 'Keith'}, {'name': 'Mick'}]
}

First, we’ll add our namespace configuration to a custom options class.

from marshmallow import Schema, SchemaOpts


class NamespaceOpts(SchemaOpts):
    """Same as the default class Meta options, but adds "name" and
    "plural_name" options for enveloping.
    """

    def __init__(self, meta, **kwargs):
        SchemaOpts.__init__(self, meta, **kwargs)
        self.name = getattr(meta, "name", None)
        self.plural_name = getattr(meta, "plural_name", self.name)

Then we create a custom Schema that uses our options class.

class NamespacedSchema(Schema):
    OPTIONS_CLASS = NamespaceOpts

    @pre_load(pass_many=True)
    def unwrap_envelope(self, data, many, **kwargs):
        key = self.opts.plural_name if many else self.opts.name
        return data[key]

    @post_dump(pass_many=True)
    def wrap_with_envelope(self, data, many, **kwargs):
        key = self.opts.plural_name if many else self.opts.name
        return {key: data}

Our application schemas can now inherit from our custom schema class.

class UserSchema(NamespacedSchema):
    name = fields.String()
    email = fields.Email()

    class Meta:
        name = "user"
        plural_name = "users"


ser = UserSchema()
user = User("Keith", email="keith@stones.com")
result = ser.dump(user)
result  # {"user": {"name": "Keith", "email": "keith@stones.com"}}