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
Built Distribution
Hashes for marshmallow-toplevel-0.1.2.tar.gz
Algorithm | Hash digest | |
---|---|---|
SHA256 | dc34a24433bbb9b87dcf8331377e4c0a413beb96235b3516cb84908462aa373d |
|
MD5 | 36a7f70a2dcdd01b70642369028ae2a2 |
|
BLAKE2b-256 | 2ad2c983c2ada34f5fa3d820072d44feb675c5ee07f8179bdabbe03290a8baa1 |
Hashes for marshmallow_toplevel-0.1.2-py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 0855766aa85ad69197f02abeef402c8b9ff44660dbced797cf3128a1ca32aad6 |
|
MD5 | 3859af154357a1b8b822d8c02df47759 |
|
BLAKE2b-256 | 697a15962704e15dbbe6dce0f6b253f2412697a7e3c1957a1d1d8e0d3f68cf6e |