Flask-Restx Swagger 文档问题
Flask-Restx Swagger Doc issue
我收到 AttributeError: module 'flask_restx.api' has no attribute 'doc' 当它在使用 flask restx 时尝试为 API 添加额外的属性。如何修复此错误。
api.py
from flask import Flask
from flask_restx import Api, Resource
from hello import Hello
app = Flask(__name__)
api = Api(app)
api.add_resource(Hello, '/hello')
if __name__ == '__main__':
app.run(debug=True)
hello.py
from flask_restx import Resource, api
@api.doc(params={'id': 'An ID'})
class Hello(Resource):
def get(self):
return {
'data': {
'names': ['one',
'two',
'three']
}
}
我不知道您遵循了哪个教程(如果您遵循了任何教程),但是
@api.doc(params={'id': 'An ID'})
需要 Api class 的实例而不是 flask-restx.api
通常,在教程(至少是我找到的教程)中,它们展示了如何在同一个文件中完成所有这些操作。
所以如果你的代码是这样写的,那么你的代码就可以工作了:
api.py
from flask import Flask
from flask_restx import Api, Resource
from hello import Hello
app = Flask(__name__)
api = Api(app)
@api.doc(params={'id': 'An ID'})
class Hello(Resource):
def get(self):
return {
'data': {
'names': ['one',
'two',
'three']
}
}
api.add_resource(Hello, '/hello')
if __name__ == '__main__':
app.run(debug=True)
现在,这不是您想要实现的,因为我猜您希望拆分文件以具有某种结构(我也希望如此)。糟糕的是,我在网上找不到合适的教程,但这是我在我的项目中所做的(使用您的示例代码):
api > __init__.py
from flask_restx import Namespace
default_namespace = Namespace("default", ordered=True)
api > hello.py
from flask_restx import Resource
from api import default_namespace as ns
@ns.doc(params={'id': 'An ID'})
class Hello(Resource):
def get(self):
return {
'data': {
'names': ['one',
'two',
'three']
}
}
app.py(您的 api.py 文件)位于根目录
from flask import Flask
from flask_restx import Api
from hello import Hello
from api import default_namespace
app = Flask(__name__)
api = Api(app)
api.add_resource(Hello, '/hello')
api.add_namespace(default_namespace)
if __name__ == '__main__':
app.run(debug=True)
包结构是:
.
+-- app.py
+-- api
+-- __init__.py
+-- hello.py
通过声明命名空间,您实际上可以在 Swagger 中将资源组合在一起。而我之所以将命名空间放在另一个文件中(此处__init__.py
)是为了不进行循环导入。
您可以将所有装饰器与 ns.doc、ns.route、... 一起使用,就像 api 一样。 (其中 api 是一个变量;))。
顺便说一句,ns 是一个别名,如果你喜欢放别的东西,你可以在 import 语句中更改它。
请注意,这可能不是最好的方法,但对我和我的结构来说已经足够干净了。如果有更多经验的人知道如何以不同的方式执行此操作,请回复 ;)
与@Jeremie 的回答几乎相同,但只是想指出官方文档。
flask-restx中有以下语句。
Flask-RESTX provides a way to use almost the same pattern as Flask’s blueprint. The main idea is to split your app into reusable namespaces.
并附有示例:
# let's say the file name is `cat_controller`.
from flask_restx import Namespace, Resource, fields
api = Namespace('cats', description='Cats related operations')
cat = api.model('Cat', {
'id': fields.String(required=True, description='The cat identifier'),
'name': fields.String(required=True, description='The cat name'),
})
CATS = [
{'id': 'felix', 'name': 'Felix'},
]
@api.route('/')
class CatList(Resource):
@api.doc('list_cats')
@api.marshal_list_with(cat)
def get(self):
'''List all cats'''
return CATS
我们需要add_namespace()
:
from flask import Flask
from flask_restx import Api
from .cat_controller import api as ns1
from .dog_controller import api as ns2
# ...
app = Flask(__name__)
api = Api(
app,
version='1.0',
title='A title',
description='A description'
)
api.add_namespace(ns1)
api.add_namespace(ns2)
if __name__ == '__main__':
app.run(debug=True)
我收到 AttributeError: module 'flask_restx.api' has no attribute 'doc' 当它在使用 flask restx 时尝试为 API 添加额外的属性。如何修复此错误。
api.py
from flask import Flask
from flask_restx import Api, Resource
from hello import Hello
app = Flask(__name__)
api = Api(app)
api.add_resource(Hello, '/hello')
if __name__ == '__main__':
app.run(debug=True)
hello.py
from flask_restx import Resource, api
@api.doc(params={'id': 'An ID'})
class Hello(Resource):
def get(self):
return {
'data': {
'names': ['one',
'two',
'three']
}
}
我不知道您遵循了哪个教程(如果您遵循了任何教程),但是
@api.doc(params={'id': 'An ID'})
需要 Api class 的实例而不是 flask-restx.api
通常,在教程(至少是我找到的教程)中,它们展示了如何在同一个文件中完成所有这些操作。 所以如果你的代码是这样写的,那么你的代码就可以工作了:
api.py
from flask import Flask
from flask_restx import Api, Resource
from hello import Hello
app = Flask(__name__)
api = Api(app)
@api.doc(params={'id': 'An ID'})
class Hello(Resource):
def get(self):
return {
'data': {
'names': ['one',
'two',
'three']
}
}
api.add_resource(Hello, '/hello')
if __name__ == '__main__':
app.run(debug=True)
现在,这不是您想要实现的,因为我猜您希望拆分文件以具有某种结构(我也希望如此)。糟糕的是,我在网上找不到合适的教程,但这是我在我的项目中所做的(使用您的示例代码):
api > __init__.py
from flask_restx import Namespace
default_namespace = Namespace("default", ordered=True)
api > hello.py
from flask_restx import Resource
from api import default_namespace as ns
@ns.doc(params={'id': 'An ID'})
class Hello(Resource):
def get(self):
return {
'data': {
'names': ['one',
'two',
'three']
}
}
app.py(您的 api.py 文件)位于根目录
from flask import Flask
from flask_restx import Api
from hello import Hello
from api import default_namespace
app = Flask(__name__)
api = Api(app)
api.add_resource(Hello, '/hello')
api.add_namespace(default_namespace)
if __name__ == '__main__':
app.run(debug=True)
包结构是:
.
+-- app.py
+-- api
+-- __init__.py
+-- hello.py
通过声明命名空间,您实际上可以在 Swagger 中将资源组合在一起。而我之所以将命名空间放在另一个文件中(此处__init__.py
)是为了不进行循环导入。
您可以将所有装饰器与 ns.doc、ns.route、... 一起使用,就像 api 一样。 (其中 api 是一个变量;))。
顺便说一句,ns 是一个别名,如果你喜欢放别的东西,你可以在 import 语句中更改它。
请注意,这可能不是最好的方法,但对我和我的结构来说已经足够干净了。如果有更多经验的人知道如何以不同的方式执行此操作,请回复 ;)
与@Jeremie 的回答几乎相同,但只是想指出官方文档。
flask-restx中有以下语句。
Flask-RESTX provides a way to use almost the same pattern as Flask’s blueprint. The main idea is to split your app into reusable namespaces.
并附有示例:
# let's say the file name is `cat_controller`.
from flask_restx import Namespace, Resource, fields
api = Namespace('cats', description='Cats related operations')
cat = api.model('Cat', {
'id': fields.String(required=True, description='The cat identifier'),
'name': fields.String(required=True, description='The cat name'),
})
CATS = [
{'id': 'felix', 'name': 'Felix'},
]
@api.route('/')
class CatList(Resource):
@api.doc('list_cats')
@api.marshal_list_with(cat)
def get(self):
'''List all cats'''
return CATS
我们需要add_namespace()
:
from flask import Flask
from flask_restx import Api
from .cat_controller import api as ns1
from .dog_controller import api as ns2
# ...
app = Flask(__name__)
api = Api(
app,
version='1.0',
title='A title',
description='A description'
)
api.add_namespace(ns1)
api.add_namespace(ns2)
if __name__ == '__main__':
app.run(debug=True)