Fields masks

Flask-RESTX support partial object fetching (aka. fields mask) by supplying a custom header in the request.

By default the header is X-Fields but it can be changed with the RESTX_MASK_HEADER parameter.

Syntax

The syntax is actually quite simple. You just provide a coma separated list of field names, optionally wrapped in brackets.

# These two mask are equivalents
mask = '{name,age}'
# or
mask = 'name,age'
data = requests.get('/some/url/', headers={'X-Fields': mask})
assert len(data) == 2
assert 'name' in data
assert 'age' in data

To specify a nested fields mask, simply provide it in bracket following the field name:

mask = '{name, age, pet{name}}'

Nesting specification works with nested object or list of objects:

# Will apply the mask {name} to each pet
# in the pets list.
mask = '{name, age, pets{name}}'

There is a special star token meaning “all remaining fields”. It allows to only specify nested filtering:

# Will apply the mask {name} to each pet
# in the pets list and take all other root fields
# without filtering.
mask = '{pets{name},*}'

# Will not filter anything
mask = '*'

Usage

By default, each time you use api.marshal or @api.marshal_with, the mask will be automatically applied if the header is present.

The header will be exposed as a Swagger parameter each time you use the @api.marshal_with decorator.

As Swagger does not permit exposing a global header once it can make your Swagger specifications a lot more verbose. You can disable this behavior by setting RESTX_MASK_SWAGGER to False.

You can also specify a default mask that will be applied if no header mask is found.

class MyResource(Resource):
    @api.marshal_with(my_model, mask='name,age')
    def get(self):
        pass

Default mask can also be handled at model level:

model = api.model('Person', {
    'name': fields.String,
    'age': fields.Integer,
    'boolean': fields.Boolean,
}, mask='{name,age}')

It will be exposed into the model x-mask vendor field:

{"definitions": {
    "Test": {
        "properties": {
            "age": {"type": "integer"},
            "boolean": {"type": "boolean"},
            "name": {"type": "string"}
        },
        "x-mask": "{name,age}"
    }
}}

To override default masks, you need to give another mask or pass * as mask.