P
P
Philip Bondarev2018-10-25 23:29:43
Python
Philip Bondarev, 2018-10-25 23:29:43

How to add additional data to ModelSchema flask-marshmallow?

I'm writing an API for Flask-RESTplus using Flask-Marshmallow . There is a need to add some information to the response generated via schema.dump(some_data) . For example, I have a Flask-SQLAlchemy model :

class User(mixins.PaginatedAPIMixin, db.Model):
    id = db.Column(db.Integer, primary_key=True, unique=True)
    username = db.Column(db.String(45), nullable=False, unique=True)
    password_hash = db.Column(db.String(128), unique=True)

There is also a resource:
resource
@api.route('/', endpoint='users')
class UsersResource(Resource):
    @api.param('page', description='Page number :int:')
    @api.param('per_page', description='Items per page :int:')
    def get(self):
        args = parse_get_args(page=int, per_page=int)
        users = User.get_paginated(User.query, self, args['page'], args['per_page'])
        schema = UsersSchema(many=True)
        dumped_data = schema.dump(users['items']).data
        dumped_data.append({'_links': users['_links'], '_meta': users['_meta']})
        return schema.jsonify(dumped_data)
UsersSchema is ModelSchema from Flask-Marshmallow (pages are just examples, as pagination goes into mixins.PaginatedAPIMixin ):
class UsersSchema(ma.ModelSchema):
    class Meta:
        model = User
        fields = ('id', 'username')

So, in the get() method of the UsersResource resource , in the users variable , as a result of calling the get_paginated() method of the model, the following dictionary is stored ( items are user objects):
users
{'items': items,
'_meta': {
    'page': 1,
    'per_page': 20,
    'total_pages': 1,
    'total_items': 2
},
'_links': {
    'self': 'api/v1/users/?page=1&per_page=20',
    'next': None,
    'prev': None
}}

The catch is that at least dumped_data.append({'_links': users['_links'], '_meta': users['_meta']}) adds the dictionary to the list, the subsequent call to schema.jsonify(dumped_data) cuts it contains all the fields not specified in the ModelSchema ... As a result, this is what happens:
Something like this
[
    {
        "id": 1,
        "username": "spam"
    },
    {
        "id": 2,
        "username": "egg"
    },
    {}
]

And I would like this:
I wish so
[
    "items": [
        {
            "id": 1,
            "username": "spam"
        },
        {
            "id": 2,
            "username": "egg"
        }
    ],
    "_links": {
        "self": "api/v1/users/?page=1&per_page=20"
    },
    "_meta": {
        "page": 1,
        "per_page": 20,
        "total_pages": 1,
        "total_items": 2
    },
]

Through self.declared_fields.update(additional_fields) in the ModelSchema constructor I tried, it only displays if the new field being added is already contained in the fields tuple ...
While the only solution is to use not schema.jsonify() , but flask.jsonify() , then everything is given OK, but I think it's kind of crooked.

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question