Как сгенерировать машиночитаемую спецификацию yaml существующего API, написанного на flask-restplus?
У меня есть простой API, написанный с помощью flask-restplus:
from flask import Flask
from flask_restplus import Resource, Api
app = Flask(__name__) # Create a Flask WSGI application
api = Api(app) # Create a Flask-RESTPlus API
@api.route('/hello') # Create a URL route to this resource
class HelloWorld(Resource): # Create a RESTful resource
def get(self): # Create GET endpoint
return {'hello': 'world'}
if __name__ == '__main__':
app.run(debug=True)
Когда я перехожу к loacalhost:5000/
в браузере я получаю базовую документацию по Swagger, но не могу найти, где я могу получить машиночитаемое представление простого yaml API, не должно ли оно также генерироваться автоматически?
1 ответ
Я не смог найти никакой информации о "генерации документации Swagger Yaml" в официальных документациях на flask-restplus. Итак, я решил изучить исходный код и обнаружил, что Swagger
Класс реализует генерацию документации Swagger для экземпляра API.
Swagger
класс в исходном коде flask-restplus является оболочкой документации Swagger для экземпляра API. Все методы в этом классе предполагают, что данные API сериализуются в виде словаря JSON. Например, рассмотрим as_dict()
функция этого класса, которая сериализует полную спецификацию Swagger как сериализуемый dict. Посмотрите на строку документации для этой функции:
from flask import Flask
from flask_restplus import Resource, Api
from flask_restplus.api import Swagger
app = Flask(__name__)
api = Api(app)
swag = Swagger(api)
print(swag.as_dict.__doc__)
#Output:
Output the specification as a serializable ``dict``.
:returns: the full Swagger specification in a serializable format
:rtype: dict
Возможно, я ошибаюсь, но исходный код предполагает, что документация по API возвращается только как JSON
который доступен на http://localhost:5000/swagger.json
по умолчанию. Я не мог найти что-нибудь для YAML.
Но есть обходной путь для создания документации YAML для вашего API. Я использовал json
а также yaml
библиотеки, чтобы сбросить ответ JSON от /swagger.json
в YAML и сохранить его в yamldoc.yml
, Вы можете вызвать это, перейдя в http://localhost:5000/swagger.yml
, Полный код:
from flask import Flask
from flask_restplus import Resource, Api
from flask_restplus.api import Swagger
import requests
import json, yaml
app = Flask(__name__) # Create a Flask WSGI application
api = Api(app) # Create a Flask-RESTPlus API
@api.route('/hello') # Create a URL route to this resource
class HelloWorld(Resource): # Create a RESTful resource
def get(self):
return {'hello': 'world'}
@api.route('/swagger.yml')
class HelloWorld(Resource):
def get(self):
url = 'http://localhost:5000/swagger.json'
resp = requests.get(url)
data = json.loads(resp.content)
with open('yamldoc.yml', 'w') as yamlf:
yaml.dump(data, yamlf, allow_unicode=True)
return {"message":"Yaml document generated!"}
if __name__ == '__main__':
app.run(debug=True)
Надеюсь, это поможет.
Из ответа @amanb я заставил свой api вернуть файл yaml без каких-либо запросов. Согласно документации flask restplus (или самой последней вилки flask restx), можно экспортировать спецификации Swagger, соответствующие вашему API, используя:
from flask import json
from myapp import api
print(json.dumps(api.__schema__))
Итак, вместо использования requests
Я предпочел использовать api.__schema__
.
Поскольку моя цель - предоставить файл для загрузки во время запроса, необходимо использовать send_file
функция Flask
. Кроме того, этот файл можно позже удалить из каталога, чтобы мы могли использоватьafter_this_request
декоратор Flask
для вызова аннотированной функции, которая удалит файл. Полный код:
import os
import json
import yaml
from flask import Flask, after_this_request, send_file, safe_join, abort
from flask_restplus import Resource, Api
from flask_restplus.api import Swagger
app = Flask(__name__) # Create a Flask WSGI application
api = Api(app) # Create a Flask-RESTPlus API
@api.route('/hello') # Create a URL route to this resource
class HelloWorld(Resource): # Create a RESTful resource
def get(self):
return {'hello': 'world'}
@api.route('/swagger.yml')
class HelloWorld(Resource):
def get(self):
data = json.loads(json.dumps(api.__schema__))
with open('yamldoc.yml', 'w') as yamlf:
yaml.dump(data, yamlf, allow_unicode=True, default_flow_style=False)
file = os.path.abspath(os.getcwd())
try:
@after_this_request
def remove_file(resp):
try:
os.remove(safe_join(file, 'yamldoc.yml'))
except Exception as error:
log.error("Error removing or closing downloaded file handle", error)
return resp
return send_file(safe_join(file, 'yamldoc.yml'), as_attachment=True, attachment_filename='yamldoc.yml', mimetype='application/x-yaml')
except FileExistsError:
abort(404)
if __name__ == '__main__':
app.run(debug=True)