flask-restplus
flask-restplus copied to clipboard
Swagger input and output models example broken
flask-restplus==0.9.2
Documentation here: http://flask-restplus.readthedocs.io/en/latest/swagger.html#input-and-output-models
Seems to suggest this should work:
from flask import Blueprint, request
from flask_restplus import Api, Resource, fields
bp = Blueprint('state_machine_api', __name__)
api = Api(bp, version='1.0', title='Labeling State Machines',
description='Automated tasks associated with labeling')
fields = api.model('MyModel', {
'name': fields.String(description='The name', required=True),
'type': fields.String(description='The object type', enum=['A', 'B']),
'age': fields.Integer(min=0),
})
@api.model(fields={'name': fields.String, 'age': fields.Integer})
class Person(fields.Raw):
def format(self, value):
return {'name': value.name, 'age': value.age}
@api.route('/my-resource/<id>', endpoint='my-resource')
@api.doc(params={'id': 'An ID'})
class MyResource(Resource):
@api.doc(model=fields)
def get(self, id):
return {}
@api.doc(model='MyModel', body=Person)
def post(self, id):
return {}
But:
(labeler) localhost% python views/test.py
Traceback (most recent call last):
File "views/test.py", line 15, in <module>
@api.model(fields={'name': fields.String, 'age': fields.Integer})
AttributeError: 'Model' object has no attribute 'String'
(labeler) localhost% python -V
Python 2.7.10
Frankly I'm not sure how it's supposed to go. Commenting out the fields =
such that the references to fields
uses the import:
Traceback (most recent call last):
File "views/test.py", line 15, in <module>
@api.model(fields={'name': fields.String, 'age': fields.Integer})
File "/Users/cyounkins/.virtualenvs/labeler/lib/python2.7/site-packages/flask_restplus/namespace.py", line 137, in model
model = Model(name, model, mask=mask)
File "/Users/cyounkins/.virtualenvs/labeler/lib/python2.7/site-packages/flask_restplus/model.py", line 46, in __init__
super(Model, self).__init__(*args, **kwargs)
TypeError: 'NoneType' object is not iterable
I could reproduce both these errors:
-
AttributeError: 'Model' object has no attribute 'String'
-
TypeError: 'NoneType' object is not iterable
Error 1 is clearly happening because of the declaration fields = api.model(...
is overriding the reference of the import from flask_restplus import fields
. Changing the variable to something like my_model
and substituting its references will solve this.
Error 2 is not clear to me. With the usage of the decorator @api.model(fields={'name': fields.String, 'age': fields.Integer})
, it tries to instantiate a ModelBase
and throws the TypeError when calling super(ModelBase, self).__init__(*args, **kwargs)
in the ModelBase.__init__
(don't know why).
Following the @api.model
definition, if I change the parameter name in the decorator from fields
to model
(@api.model(model={'name': fields.String, 'age': fields.Integer})
) I get the following error:
Traceback (most recent call last):
File "example.py", line 17, in <module>
class Person(fields.Raw):
TypeError: 'Model' object is not callable
I'm not sure if the error begins from a possibly wrong parameter name (fields instead of model) or if the usage is right and there is some problem with the model creation. Could anyone clarify this?
Got a little bit further with the second error. Clarifying my own question, it seems the usage of @api.model
with the fields
parameter is right and the problem is with the creation of the model. Since no model is being passed in @api.model
it is by default None
and when it gets to the creation of a ModelBase
the None
value is passed through args
(args==(None,)
):
class ModelBase(object):
def __init__(self, name, *args, **kwargs):
super(ModelBase, self).__init__(*args, **kwargs)
Where it gives the TypeError: 'NoneType' object is not iterable
.
Changing the model function to pass the model argument as a named parameter seems to fix this:
def model(self, name=None, model=None, mask=None, **kwargs):
cls = OrderedModel if self.ordered else Model
model = cls(name, model, mask=mask) # change to: cls(name, model=model, mask=mask)
model.__apidoc__.update(kwargs)
return self.add_model(name, model)
The problem is that even after the correct creation of a model we get to this error:
Traceback (most recent call last):
File "example.py", line 17, in <module>
class Person(fields.Raw):
TypeError: 'Model' object is not callable
@hygorxaraujo Did you ever make any more headway with this? I am trying to puzzle through the same now and am stumped.
@Fail-Safe, I stopped working on it, sorry.
I seem to be facing the same issue, has anyone found a workaround for this?