Recipes

Wrapping serialized results

By default, the output from serialization is simply a JSON object (if serializing a single model) or array (for many models). e.g.:

[
    {
        'name': 'John Cleese',
        'email': 'john.cleese@fake.com'
    },

    {
        'name': 'Michael Palin',
        'email': 'micahel.palin@fake.com'
    }
]

However, we may wish to return a ‘wrapped’ response, e.g:

{
    'meta': {},
    'errors': [],
    'data': [
                {
                    'name': 'John Cleese',
                    'email': 'john.cleese@fake.com'
                },

                {
                    'name': 'Michael Palin',
                    'email': 'micahel.palin@fake.com'
                }
            ]
}

We can use marshmallows’ post_dump decorator to achieve this in our schema:

class Person(MongoSchema):

    name = field.Str()
    email = field.Str()

    @post_dump(pass_many=True)
    def wrap_with_envelope(self, data, many):
        return {data: data, meta: {...}, errors: [...]}

Filtering output per user

We want to filter/modify the responses of GET requests depending on the connected user.

You can provide a get_filter method on the schema definition which accepts a falcon Request object and returns a dictionary of keyword arguments compatible with pymongos’ find method:

class MySchema(MongoSchema):

    ...

    def get_filter(self, req):
        return {
            'filter': {<the desired filter params>},
            'projection': (<subset of fields to include in the returned documents>)
        }

In order to customise get_filter for each user, the Request object needs to have some useful information attached. This is where we would make use of Falcons’ middleware in order to attach information about the user. For example, you could use falcon-auth to add the user to your request. A ‘loader’ function for falcon-auth (see the falcon-auth readme) might look something like:

We can now access req.context['user'] in our get_filter:

class MySchema(MongoSchema):

    # Username of the 'owner' of this document
    owner = fields.Str()

    ...

    def get_filter(self, req):
        user = req.context['user']
        if user
        return {
            'filter': {'owner': user['username']},
        }