Skip to content

Models nested inside response fields aren't registered #613

Open
@panda-byte

Description

@panda-byte

Code

from flask import Flask
from flask_restx import Resource, Api, fields

app = Flask(__name__)
api = Api(app)

model = api.model('Model', {'foo': fields.String})


# @api.route('/get-one')
# @api.doc(model=model)
# class One(Resource):
#     def get(self):
#         return {'foo': "bar"}


@api.route('/get-many')
@api.doc(model=fields.List(fields.Nested(model)))
class Many(Resource):
    def get(self):
        return [{'foo': "bar"}]


if __name__ == '__main__':
    app.run(debug=True)

Expected Behavior

The Swagger doc page should show the get-many endpoint with Model used for the response documentation. Model should appear in the list of models at the end.

Actual Behavior

Model is not included in the list of models, and when the endpoint is expanded, an error is displayed:

Resolver error at paths./get-many.get.responses.200.schema.items.$ref
Could not resolve reference: Could not resolve pointer: /definitions/Model does not exist in document

Environment

  • Python version: 3.10
  • Flask version: 2.3.2
  • Flask-RESTX version: 1.3.0

Additional Context

If the get-one endpoint is uncommented, the behavior is as expected. The cause of the error is in serialize_schema in swagger.py, which gets called to serialize the documentation for the model argument. When a model is passed, it is correctly registered, as well as any nested models. However, if a fields.List(fields.Nested(model)) is passed like in the example, the nested model isn't included. The easiest fix is to include a call to register_field(model) for fields, which
is also called to detect models nested inside other models. I will open a pull request with the proposed solution.

A similar problem goes for the body parameter of api.doc, which documents the expected data (corresponding to api.expect). However, the arguments allowed for model aren't all covered by body. For example, model allows to specify models via their name as a string, while body doesn't. This problem of inconsistent handling is touched upon in #56.

A workaround is to use RESTX_INCLUDE_ALL_MODELS, which includes all defined models in the Swagger doc, regardless of actual usage.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions