Description
Code
I'm trying to organize my code so that model definitions are shared, in order to reduce clutter, and so that pure API logic ends up in its own files. Here's the structure that I've got right now.
In app.py
(the entry point):
from api import api
from flask import Flask
app = Flask(__name__)
api.init_app(app)
In api/__init__.py
:
from flask_restx import Api
from .demo import api as demo_ns
from .models import register_models
api = Api()
register_models(api)
api.add_namespace(demo_ns)
In api/models.py
:
from flask_restx import fields
models = {
'My Cool Model': {'my_field': fields.String(description='A cool field!')}
}
def register_models(api):
for model_name, model_data in models.items():
api.model(name=model_name, model=model_data)
In api/demo.py
:
from flask import json
from flask_restx import Namespace, Resource, Model
api = Namespace('demo', description='Demo and testing endpoints')
@api.route('/hello')
class HelloWorld(Resource):
@api.expect(Model('My Cool Model'), validate=True)
@api.response(200, description='Success', model=Model('My Cool Model'))
def post(self):
return json.jsonify({'my_field': 'hello!'})
Repro Steps (if applicable)
- Run the above code.
- Note that the generated documentation does not have a definition for the data returned on a 200 response, but it does have a definition for the data expected in the request.
- Change the
model
parameter in theapi.response
decorator to[Model('My Cool Model')]
. - Reload the documentation.
- Note that the generated documentation now specifies that a list of objects are returned on a 200 response.
Expected Behavior
Constructing a model object should work the same in both places; if constructing an already-defined model object works for the api.expect decorator, it should also work for the api.response decorator, and vice versa.
Actual Behavior
With the above code, the model will properly render in the documentation for the api.expect decorator, but it will not render for the api.response decorator. However, changing the model parameter in the api.response decorator from Model('My Cool Model')
to [Model('My Cool Model')]
(i.e. encapsulating it in a list) causes it to render. This is fine for when I want my defined API to produce a list of objects, but not so good for when I want my defined API to produce a single object.
Environment
- Python version
Running the python3.7-slim docker image, exact version is below:
Python 3.7.5 (default, Nov 15 2019, 02:40:28)
[GCC 8.3.0] on linux
- Flask version: 1.1.1
- Flask-RESTX version: 0.1.1
- Other installed Flask extensions: N/A
Additional Context
My current workaround is to include a make_model
function in the api/models.py
file:
def make_model(api, model_name):
return api.model(model_name, models[model_name])
This function can then be imported and called in api/demo.py
as follows, and produces the expected result in the documentation:
from .models import make_model
# snip
@api.response(200, description='Success', model=make_model(api, 'My Cool Model'))