Skip to main content

Validate top-level lists with all the power of marshmallow

Project description

marshmallow-toplevel

Load and validate top-level lists with all the power of marshmallow.

Installation

pip install marshmallow-toplevel

Usage

from marshmallow import fields
from marshmallow_toplevel import TopLevelSchema


class BatchOfSomething(TopLevelSchema):
    _toplevel = fields.Nested(
        SomethingSchema,
        required=True,
        many=True,
        validate=any_validation_logic_applied_to_list
    )

Rationale

Imagine that you have an API endpoint (or any other program that accepts user input), which is intended to accept multiple blog articles and save them to a database. Semantically, your data is a list of dictionaries:

[
    {"id": 1, "title": "Hello World!"},
    {"id": 2, "title": "Yet another awesome article."},
    ...
]

You describe article object schema and put constraints on your data:

from marshmallow import Schema, fields, validate


class ArticleSchema(Schema):
    id = fields.Int(required=True)
    title = fields.Str(required=True, validate=validate.Length(min=2, max=256))

But you also want to put some constraints onto outer list itself, for example, you want it to have length between 1 and 10. How do you describe it in terms of marshmallow?

Obvious solution: nest your data

class BatchOfArticles(Schema):
    articles = fields.Nested(
        ArticleSchema,
        required=True,
        many=True,
        validate=validate.Length(1, 10)
    )

But now a client have to send data this way, with this extra dictionary around:

{
    "articles": [
        {"id": 1, "title": "Hello World!"},
        {"id": 2, "title": "Yet another awesome article."},
        ...
    ]
}

It makes your API not so beautiful and user-friendly.

Good solution: use marshmallow-toplevel

With marshmallow-toplevel you can describe you data this way:

from marshmallow_toplevel import TopLevelSchema


class BatchOfArticles(TopLevelSchema):
    _toplevel = fields.Nested(
        ArticleSchema,
        required=True,
        many=True,
        validate=validate.Length(1, 10)
    )

Notice that schema inherits from TopLevelSchema and uses this special _toplevel key. It means that the field under this key describes top level object. You can define any constrains that you can define in marshmallow and it will just work:

schema = BatchOfArticles()

# validation should fail
errors = schema.validate([])
assert errors  # length < 1
errors = schema.validate([{"id": i, "title": "title"} for i in range(100)])
assert errors  # length > 10

# validation should succeed
errors = schema.validate([{"id": i, "title": "title"} for i in range(5)])
assert not errors

You can also use load for this schema as usual:

data = schema.load([{"id": "10", "title": "wow!"}])
print(data)
# [{"id": 10, "title": "wow!"}]

Now a client can send data as a list without redundancy.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

marshmallow-toplevel-0.1.3.tar.gz (4.1 kB view hashes)

Uploaded source

Built Distribution

Supported by

AWS AWS Cloud computing Datadog Datadog Monitoring Facebook / Instagram Facebook / Instagram PSF Sponsor Fastly Fastly CDN Google Google Object Storage and Download Analytics Huawei Huawei PSF Sponsor Microsoft Microsoft PSF Sponsor NVIDIA NVIDIA PSF Sponsor Pingdom Pingdom Monitoring Salesforce Salesforce PSF Sponsor Sentry Sentry Error logging StatusPage StatusPage Status page