Gerar documentação de API abrangente e precisa é uma parte crítica, mas muitas vezes tediosa, do desenvolvimento de software. A OpenAPI Specification (anteriormente conhecida como Swagger) emergiu como o padrão da indústria para definir APIs RESTful. Ela fornece um formato legível por máquina que permite que tanto humanos quanto computadores descubram e entendam as capacidades de um serviço sem acesso ao código-fonte, documentação ou através da inspeção de tráfego de rede.1
Embora muitos frameworks ofereçam plugins para gerar especificações OpenAPI a partir de anotações de código (como docstrings), existem cenários onde você pode precisar de um controle mais direto e programático sobre a criação da especificação. Isso pode ser porque você está trabalhando com um sistema legado, um framework não padrão, ou você precisa gerar uma especificação para uma API que é composta por múltiplos microsserviços.
É aqui que o pyswagger
entra. É uma poderosa biblioteca Python que funciona como um kit de ferramentas para OpenAPI. Embora seja frequentemente usado como um cliente de API para consumir serviços definidos por uma especificação OpenAPI, seu verdadeiro poder reside em seu modelo de objeto, que permite construir, manipular e validar uma especificação programaticamente.
Neste tutorial abrangente, vamos percorrer o processo de usar o pyswagger
para gerar, de forma manual, porém automática, uma especificação completa da OpenAPI 3.0 para uma aplicação web simples em Python construída com Flask. Construiremos a especificação do zero, peça por peça, demonstrando como os objetos do pyswagger
mapeiam diretamente para os componentes do padrão OpenAPI. Ao final, você não terá apenas um arquivo openapi.json
gerado, mas também uma UI de documentação interativa e ao vivo servida diretamente de sua aplicação.
Quer uma plataforma integrada e Tudo-em-Um para sua Equipe de Desenvolvedores trabalhar com produtividade máxima?
Apidog entrega todas as suas demandas, e substitui o Postman por um preço muito mais acessível!
button
Parte 1: Configurando o Ambiente do Projeto
Antes de começarmos a gerar nossa especificação, precisamos configurar um ambiente de desenvolvimento adequado. Isso envolve criar um ambiente Python isolado para gerenciar nossas dependências e instalar as bibliotecas necessárias.
Criando Seu Espaço de Trabalho ⚙️
Primeiro, vamos criar um diretório para nosso projeto. Abra seu terminal ou prompt de comando e execute os seguintes comandos:Bash
# Create a new directory for our project
mkdir pyswagger-tutorial
cd pyswagger-tutorial
# Create a Python virtual environment
# On macOS/Linux
python3 -m venv venv
# On Windows
python -m venv venv
Um ambiente virtual é uma árvore de diretórios autocontida que inclui uma instalação Python e vários arquivos de suporte. Usar um ambiente virtual garante que os pacotes que instalamos para este projeto não entrem em conflito com pacotes instalados para outros projetos.
Agora, ative o ambiente virtual:Bash
# On macOS/Linux
source venv/bin/activate
# On Windows
.\venv\Scripts\activate
Uma vez ativado, o prompt do seu terminal deve mudar para mostrar o nome do ambiente virtual (por exemplo, (venv)
), indicando que você está trabalhando dentro dele.
Instalando Bibliotecas Necessárias
Com nosso ambiente ativo, podemos instalar as bibliotecas Python que precisaremos para este tutorial. Precisamos do próprio pyswagger
para construir a especificação, do Flask
para criar nossa API web simples e do PyYAML
porque o pyswagger
o utiliza para operações YAML.Bash
pip install "pyswagger[utils]" Flask PyYAML
A parte [utils]
ao instalar o pyswagger
é uma boa prática, pois inclui utilitários úteis, como um validador que usaremos mais tarde para verificar a correção de nossa especificação gerada.
Para uma boa gestão de projeto, é prudente fixar suas dependências em um arquivo requirements.txt
.Bash
pip freeze > requirements.txt
Seu requirements.txt
agora conterá as bibliotecas e suas versões específicas, tornando seu projeto facilmente reproduzível por outros.
Criando a Aplicação Flask Básica
Agora, vamos criar uma aplicação Flask mínima. Isso servirá como base da API que vamos documentar.
No diretório do seu projeto, crie um novo arquivo chamado app.py
e adicione o seguinte código:Python
# app.py
from flask import Flask, jsonify
# Initialize the Flask application
app = Flask(__name__)
@app.route("/")
def index():
""" A simple endpoint to check if the app is running. """
return jsonify({"message": "API is up and running!"})
if __name__ == "__main__":
# Runs the Flask app on http://127.0.0.1:5000
app.run(debug=True)
Este código configura um servidor web muito simples com um único endpoint. Para executá-lo, certifique-se de que seu ambiente virtual ainda está ativo e execute o seguinte comando em seu terminal:Bash
python app.py
Você deverá ver uma saída indicando que o servidor está rodando, algo como isto:
* Serving Flask app 'app'
* Debug mode: on
* Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
Você pode agora abrir seu navegador web ou usar uma ferramenta como curl
para visitar http://127.0.0.1:5000
. Você deverá ver a resposta JSON: {"message": "API is up and running!"}
.
Com nosso ambiente básico e esqueleto de aplicação prontos, podemos agora mergulhar nos conceitos centrais do pyswagger
.
Parte 2: Entendendo o Modelo de Objeto do pyswagger
Para usar o pyswagger
de forma eficaz na geração de uma especificação, você primeiro precisa entender como seu modelo de objeto corresponde à estrutura de um documento OpenAPI. Uma especificação OpenAPI é essencialmente um grande objeto JSON ou YAML com um schema específico. O pyswagger
fornece classes e objetos Python que espelham este schema, permitindo que você construa a especificação de uma maneira mais intuitiva e orientada a objetos.
Conceitos Centrais da OpenAPI 3.0 Specification 📜
Um documento OpenAPI 3.0 possui alguns campos-chave de nível superior:
openapi
: Uma string especificando a versão da OpenAPI Specification (por exemplo,'3.0.0'
).info
: Um objeto fornecendo metadados sobre a API. Isso inclui otitle
,version
,description
e informações de contato.servers
: Um array de objetos server, que definem as URLs base para a API.paths
: O campo mais importante. Este objeto contém todos os endpoints de API disponíveis (paths) e as operações HTTP (GET, POST, PUT, DELETE, etc.) que podem ser realizadas neles.components
: Um objeto que contém um conjunto de objetos reutilizáveis para diferentes partes da especificação. Isso é fundamental para manter sua especificação DRY (Don't Repeat Yourself). Você pode definirschemas
reutilizáveis (modelos de dados),responses
,parameters
,examples
, e mais.
Mapeando OpenAPI para Objetos do pyswagger
O pyswagger
fornece um mapeamento limpo desses conceitos OpenAPI para objetos Python. Vamos explorar os principais que usaremos.
O objeto central no pyswagger
é o App
. Você pode pensar em uma instância de App
como a raiz do seu documento OpenAPI.Python
from pyswagger import App
# The root of the specification document
# We initialize it with a version, but it can also load from a URL or file
root_app = App(version='3.0.0')
Uma vez que você tenha seu objeto App
, você pode começar a popular seus atributos, que correspondem diretamente aos campos OpenAPI. O pyswagger
usa um padrão builder, permitindo uma sintaxe fluente e legível.
Info e Servers
As seções info
e servers
são diretas de popular.Python
# Populating the 'info' object
root_app.info.title = "User API"
root_app.info.version = "1.0.0"
root_app.info.description = "A simple API to manage users, used for the pyswagger tutorial."
# Populating the 'servers' array
# You create a Server object and append it
server = root_app.prepare_obj('Server', {'url': 'http://127.0.0.1:5000', 'description': 'Local development server'})
root_app.servers.append(server)
Paths e Operations
Paths são definidos no objeto App
. Você adiciona novos paths e então define as operações (métodos HTTP) dentro deles. Cada operação é configurada com detalhes como um summary
, description
, parameters
, um requestBody
e responses
.Python
# Defining a path and an operation
# This doesn't execute anything; it just builds the object structure.
path_item = root_app.define_path('/users')
get_op = path_item.define_op('get')
get_op.summary = "Retrieve a list of all users"
Components: Schemas, Parameters e Responses
O verdadeiro poder de uma especificação OpenAPI bem estruturada vem de componentes reutilizáveis. Em vez de definir a estrutura de um "User" objeto toda vez que ele aparece em uma resposta, você o define uma vez em components/schemas
e então o referencia usando um ponteiro $ref
. O pyswagger
lida com isso elegantemente.
Schema
: Um objeto Schema
define um modelo de dados. Você pode especificar seu tipo (object
, string
, integer
) e suas propriedades.Python
# Preparing a Schema object for a User
user_schema = root_app.prepare_obj('Schema', {
'type': 'object',
'properties': {
'id': {'type': 'integer', 'format': 'int64'},
'username': {'type': 'string'},
'email': {'type': 'string', 'format': 'email'}
},
'required': ['id', 'username', 'email']
})
# Add it to the reusable components
root_app.components.schemas['User'] = user_schema
Parameter
: Um objeto Parameter
define um único parâmetro de operação. Você especifica seu nome, onde ele está localizado (in
: 'path'
, 'query'
, 'header'
ou 'cookie'
) e seu schema.Python
# Preparing a Parameter object for a user ID in the path
user_id_param = root_app.prepare_obj('Parameter', {
'name': 'user_id',
'in': 'path',
'description': 'ID of the user to retrieve',
'required': True,
'schema': {'type': 'integer'}
})
Response
: Um objeto Response
define a estrutura de uma resposta para um código de status HTTP específico. Inclui uma description
e o content
, que especifica o tipo de mídia (por exemplo, application/json
) e seu schema.Python
# Preparing a Response object for a 200 OK response returning a single user
# Note the use of '$ref' to point to our reusable User schema
ok_user_response = root_app.prepare_obj('Response', {
'description': 'Successful retrieval of a user',
'content': {
'application/json': {
'schema': {'$ref': '#/components/schemas/User'}
}
}
})
Compreender este mapeamento é a chave para construir sua especificação. Você está essencialmente construindo um grafo de objetos Python que o pyswagger
irá posteriormente serializar em um arquivo JSON ou YAML OpenAPI válido.
Parte 3: Construindo uma API Simples com Flask
Para tornar nosso exercício de documentação prático, precisamos de uma API real para documentar. Vamos expandir nossa simples aplicação Flask da Parte 1 em uma API REST mínima para gerenciar uma lista de usuários. Esta API servirá como a "fonte da verdade" que descreveremos com o pyswagger
.
Projetando uma API Simples de "Usuário" 📝
Implementaremos quatro endpoints básicos que representam operações CRUD (Create, Read, Update, Delete) comuns:
GET /users
: Recuperar uma lista de todos os usuários.POST /users
: Criar um novo usuário.GET /users/{user_id}
: Obter um único usuário pelo seu ID.DELETE /users/{user_id}
: Excluir um usuário pelo seu ID.
Para simplificar, usaremos um dicionário Python simples como nosso "banco de dados" em memória. Em uma aplicação do mundo real, isso seria uma conexão com um banco de dados como PostgreSQL ou MongoDB.
Implementando os Endpoints Flask
Vamos atualizar nosso arquivo app.py
para incluir a lógica para estes endpoints. Substitua o conteúdo de app.py
pelo seguinte:Python
# app.py
from flask import Flask, jsonify, request, abort
app = Flask(__name__)
# --- In-Memory Database ---
# A simple dictionary to store our users.
# The key is the user_id (integer), and the value is the user data (dict).
USERS_DB = {
1: {"username": "alice", "email": "alice@example.com"},
2: {"username": "bob", "email": "bob@example.com"},
3: {"username": "charlie", "email": "charlie@example.com"},
}
# A counter to simulate auto-incrementing IDs for new users
LAST_INSERT_ID = 3
# --- API Endpoints ---
@app.route("/users", methods=["GET"])
def get_users():
""" Returns a list of all users. """
# We need to convert the dictionary to a list of user objects, including their IDs.
users_list = []
for user_id, user_data in USERS_DB.items():
user = {'id': user_id}
user.update(user_data)
users_list.append(user)
return jsonify(users_list)
@app.route("/users", methods=["POST"])
def create_user():
""" Creates a new user. """
global LAST_INSERT_ID
if not request.json or 'username' not in request.json or 'email' not in request.json:
abort(400, description="Missing username or email in request body.")
LAST_INSERT_ID += 1
new_user_id = LAST_INSERT_ID
new_user = {
"username": request.json["username"],
"email": request.json["email"],
}
USERS_DB[new_user_id] = new_user
# The response should include the ID of the newly created user
response_user = {'id': new_user_id}
response_user.update(new_user)
return jsonify(response_user), 201
@app.route("/users/<int:user_id>", methods=["GET"])
def get_user(user_id):
""" Returns a single user by their ID. """
if user_id not in USERS_DB:
abort(404, description=f"User with ID {user_id} not found.")
user_data = USERS_DB[user_id]
user = {'id': user_id}
user.update(user_data)
return jsonify(user)
@app.route("/users/<int:user_id>", methods=["DELETE"])
def delete_user(user_id):
""" Deletes a user by their ID. """
if user_id not in USERS_DB:
abort(404, description=f"User with ID {user_id} not found.")
del USERS_DB[user_id]
# A 204 No Content response is standard for successful deletions
return '', 204
if __name__ == "__main__":
app.run(debug=True, port=5000)
Agora, se você executar python app.py
novamente, você terá uma API totalmente funcional (embora simples). Você pode testá-la com curl
ou uma ferramenta similar:
- Obter todos os usuários:
curl http://127.0.0.1:5000/users
- Obter um usuário específico:
curl http://127.0.0.1:5000/users/1
- Criar um usuário:
curl -X POST -H "Content-Type: application/json" -d '{"username": "david", "email": "david@example.com"}' http://127.0.0.1:5000/users
- Excluir um usuário:
curl -X DELETE http://127.0.0.1:5000/users/3
Com nossa API implementada, temos um alvo concreto para nossos esforços de documentação. O próximo passo é usar o pyswagger
para descrever cada um desses endpoints em detalhes.
Parte 4: Gerando Automaticamente a Especificação OpenAPI com pyswagger
Este é o cerne do nosso tutorial. Agora criaremos um script Python separado que importa o pyswagger
, define a estrutura de nossa API usando seu modelo de objeto e então serializa essa estrutura em um arquivo openapi.json
completo. Esta abordagem desacopla a geração da especificação da lógica da aplicação, o que pode ser um padrão muito limpo e de fácil manutenção.
Criando o Gerador de Especificação
No diretório do seu projeto, crie um novo arquivo chamado generate_spec.py
. Este script será responsável por construir e salvar nossa especificação OpenAPI.
Construindo a Especificação, Passo a Passo
Vamos construir o script generate_spec.py
peça por peça.
1. Imports e Inicializando o App
Primeiro, precisamos importar o objeto App
do pyswagger
e o PyYAML
para ajudar a despejar o arquivo final. Criaremos nosso objeto App
raiz e popular as seções básicas info
e servers
, assim como discutimos na Parte 2.Python
# generate_spec.py
import json
from pyswagger import App
from pyswagger.contrib.client.requests import Client
# --- 1. Initialize the root App object ---
app = App(version='3.0.0')
# --- 2. Populating the Info & Servers sections ---
app.info.title = "User API"
app.info.version = "1.0.0"
app.info.description = "A simple API to manage users, for the pyswagger tutorial."
server = app.prepare_obj('Server', {
'url': 'http://127.0.0.1:5000',
'description': 'Local development server'
})
app.servers.append(server)
2. Definindo Componentes Reutilizáveis (Schemas)
Um bom design de API evita repetição. Definiremos nosso modelo de dados User
uma vez e o reutilizaremos. Também definiremos um schema genérico Error
para nossas respostas de erro (como 404 Not Found).
Adicione o seguinte código ao generate_spec.py
:Python
# --- 3. Defining Reusable Components (Schemas) ---
# Schema for the Error response
error_schema = app.prepare_obj('Schema', {
'type': 'object',
'properties': {
'code': {'type': 'integer', 'format': 'int32'},
'message': {'type': 'string'}
}
})
app.components.schemas['Error'] = error_schema
# Schema for a single User. Note the properties match our USERS_DB structure.
user_schema = app.prepare_obj('Schema', {
'type': 'object',
'properties': {
'id': {
'type': 'integer',
'description': 'Unique identifier for the user.',
'readOnly': True # The client cannot set this value
},
'username': {
'type': 'string',
'description': 'The user\'s chosen username.'
},
'email': {
'type': 'string',
'description': 'The user\'s email address.',
'format': 'email'
}
},
'required': ['id', 'username', 'email']
})
app.components.schemas['User'] = user_schema
# Schema for creating a user (doesn't include the 'id' field)
new_user_schema = app.prepare_obj('Schema', {
'type': 'object',
'properties': {
'username': {
'type': 'string',
'description': 'The user\'s chosen username.'
},
'email': {
'type': 'string',
'description': 'The user\'s email address.',
'format': 'email'
}
},
'required': ['username', 'email']
})
app.components.schemas['NewUser'] = new_user_schema
3. Documentando os Endpoints `/users`
Agora definiremos o path `/users` e suas duas operações: GET
e POST
.
- Para
GET
, a resposta é um *array* de objetosUser
. - Para
POST
, o corpo da requisição esperará um objetoNewUser
, e a resposta bem-sucedida será um único objetoUser
(incluindo o novo ID).
Python
# --- 4. Documenting the Paths ---
# -- Path: /users --
path_users = app.define_path('/users')
# Operation: GET /users
op_get_users = path_users.define_op('get')
op_get_users.summary = "List all users"
op_get_users.description = "Returns a JSON array of all user objects."
op_get_users.tags.append('Users')
op_get_users.responses.A('200').description = "A list of users."
op_get_users.responses.A('200').content.A('application/json').schema.A(
'array', items={'$ref': '#/components/schemas/User'}
)
# Operation: POST /users
op_post_users = path_users.define_op('post')
op_post_users.summary = "Create a new user"
op_post_users.description = "Adds a new user to the database."
op_post_users.tags.append('Users')
op_post_users.requestBody.description = "User object that needs to be added."
op_post_users.requestBody.required = True
op_post_users.requestBody.content.A('application/json').schema.set_ref('#/components/schemas/NewUser')
op_post_users.responses.A('201').description = "User created successfully."
op_post_users.responses.A('201').content.A('application/json').schema.set_ref('#/components/schemas/User')
op_post_users.responses.A('400').description = "Invalid input provided."
op_post_users.responses.A('400').content.A('application/json').schema.set_ref('#/components/schemas/Error')
Observe o uso de set_ref
e A
(que significa "acesso") para uma sintaxe mais concisa na construção da estrutura de objeto aninhada.
4. Documentando os Endpoints `/users/{user_id}`
Em seguida, documentaremos o path para interagir com um único usuário. Este path inclui um parâmetro de path, `{user_id}`.
- Para
GET
, precisaremos definir este parâmetro de path. A resposta é um único objetoUser
ou um erro404
. - Para
DELETE
, também precisamos do parâmetro de path. A resposta bem-sucedida é um204 No Content
.
Python
# -- Path: /users/{user_id} --
path_user_id = app.define_path('/users/{user_id}')
# We can define the parameter once and reuse it for all operations on this path.
user_id_param = app.prepare_obj('Parameter', {
'name': 'user_id',
'in': 'path',
'description': 'ID of the user',
'required': True,
'schema': {'type': 'integer'}
})
path_user_id.parameters.append(user_id_param)
# Operation: GET /users/{user_id}
op_get_user_id = path_user_id.define_op('get')
op_get_user_id.summary = "Find user by ID"
op_get_user_id.description = "Returns a single user."
op_get_user_id.tags.append('Users')
op_get_user_id.responses.A('200').description = "Successful operation."
op_get_user_id.responses.A('200').content.A('application/json').schema.set_ref('#/components/schemas/User')
op_get_user_id.responses.A('404').description = "User not found."
op_get_user_id.responses.A('404').content.A('application/json').schema.set_ref('#/components/schemas/Error')
# Operation: DELETE /users/{user_id}
op_delete_user_id = path_user_id.define_op('delete')
op_delete_user_id.summary = "Deletes a user"
op_delete_user_id.description = "Deletes a single user from the database."
op_delete_user_id.tags.append('Users')
op_delete_user_id.responses.A('204').description = "User deleted successfully."
op_delete_user_id.responses.A('404').description = "User not found."
op_delete_user_id.responses.A('404').content.A('application/json').schema.set_ref('#/components/schemas/Error')
5. Validando e Salvando a Especificação
Finalmente, o passo mais satisfatório. Pediremos ao pyswagger
para validar nosso grafo de objetos construído contra o schema OpenAPI 3.0. Se for válido, o despejaremos em um arquivo JSON.
Adicione este bloco final de código ao generate_spec.py
:Python
# --- 5. Validate and Save the Specification ---
if __name__ == '__main__':
try:
# Validate the generated specification
app.validate()
print("Specification is valid.")
# Save the specification to a JSON file
with open('openapi.json', 'w') as f:
f.write(app.dump_json(indent=2))
print("Successfully generated openapi.json")
except Exception as e:
print(f"Validation Error: {e}")
Seu arquivo generate_spec.py
está agora completo. Execute-o a partir do seu terminal:Bash
python generate_spec.py
Se tudo estiver correto, você verá a saída:
Specification is valid.
Successfully generated openapi.json
Agora você terá um novo arquivo, openapi.json
, no diretório do seu projeto. Abra-o e explore seu conteúdo. Você verá um documento OpenAPI 3.0 perfeitamente estruturado que descreve sua API Flask em detalhes minuciosos.
Parte 5: Servindo a Documentação
Ter um arquivo openapi.json
é ótimo para máquinas e para gerar SDKs de cliente, mas para desenvolvedores humanos, uma UI interativa é muito mais útil. Nesta parte final, integraremos nossa especificação gerada em nossa aplicação Flask e a serviremos usando a popular Swagger UI.
Integrando a Especificação no Flask
Primeiro, precisamos criar um endpoint em nossa aplicação Flask que sirva o arquivo openapi.json
. Isso permite que ferramentas de documentação busquem a especificação diretamente de nossa API em execução.
Modifique app.py
para adicionar uma nova rota:Python
# app.py
# ... (keep all the existing Flask code) ...
import os
# ... (all the routes like /users, /users/{user_id}, etc.) ...
# --- Serving the OpenAPI Specification and UI ---
@app.route('/api/docs/openapi.json')
def serve_openapi_spec():
""" Serves the generated openapi.json file. """
# This assumes openapi.json is in the same directory as app.py
# In a larger app, you might want a more robust way to find the file
return app.send_static_file('openapi.json')
Para que isso funcione, o Flask precisa saber onde encontrar arquivos estáticos. Por padrão, ele procura em um diretório static
. Vamos criar um e mover nosso arquivo openapi.json
para lá.Bash
mkdir static
mv openapi.json static/
Agora, execute python app.py
e navegue até http://127.0.0.1:5000/api/docs/openapi.json
. Você deverá ver o JSON bruto de sua especificação.
Servindo UI Interativa com Swagger UI 🎨
Swagger UI é uma coleção independente de ativos HTML,2 JavaScript e CSS que gera dinamicamente uma bela documentação a partir de uma API compatível com OpenAPI. Podemos facilmente servi-la a partir de nossa aplicação Flask.
Criar um Diretório de Templates: O Flask usa um diretório chamado templates
para procurar por templates HTML.Bash
mkdir templates
Criar o Template da Swagger UI: Dentro do diretório templates
, crie um novo arquivo chamado swagger_ui.html
. Cole o seguinte código HTML nele. Este código carrega os ativos da Swagger UI de um CDN público e a configura para carregar nosso arquivo de especificação.HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>User API - Swagger UI</title>
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.17.14/swagger-ui.min.css" >
<style>
html {
box-sizing: border-box;
overflow: -moz-scrollbars-vertical;
overflow-y: scroll;
}
*, *:before, *:after {
box-sizing: inherit;
}
body {
margin:0;
background: #fafafa;
}
</style>
</head>
<body>
<div id="swagger-ui"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.17.14/swagger-ui-bundle.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.17.14/swagger-ui-standalone-preset.js"></script>
<script>
window.onload = function() {
// Begin Swagger3 UI call region
const ui = SwaggerUIBundle({
url: "/api/docs/openapi.json", // The URL for our spec
dom_id: '#swagger-ui',
deepLinking: true,
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIStandalonePreset
],
plugins: [
SwaggerUIBundle.plugins.DownloadUrl
],
layout: "StandaloneLayout"
})
// End Swagger UI call region
window.ui = ui
}
</script>
</body>
</html>
Adicionar a Rota Flask: Finalmente, adicione uma rota ao app.py
para renderizar este template HTML. Você precisará importar render_template
do Flask.Python
# At the top of app.py
from flask import Flask, jsonify, request, abort, render_template
# ... (all other routes) ...
@app.route('/api/docs/')
def serve_swagger_ui():
""" Serves the interactive Swagger UI documentation. """
return render_template('swagger_ui.html')
Juntando Tudo
A estrutura final do seu projeto deverá ser assim:
pyswagger-tutorial/
├── app.py
├── generate_spec.py
├── requirements.txt
├── static/
│ └── openapi.json
├── templates/
│ └── swagger_ui.html
└── venv/
Agora para o resultado final. Certifique-se de que sua aplicação Flask está rodando (python app.py
). Abra seu navegador web e navegue para:
http://127.0.0.1:5000/api/docs/
Você deverá ser recebido com uma bela página de documentação interativa para sua API. Você pode expandir cada endpoint, ver os schemas que definiu e até mesmo usar o botão "Try it out" para enviar requisições ao vivo para sua aplicação Flask em execução diretamente do navegador.
Conclusão
Neste tutorial, viajamos de um diretório vazio para uma API totalmente documentada. Usamos com sucesso o pyswagger
para construir programaticamente uma especificação OpenAPI 3.0 detalhada, mapeando seu modelo de objeto para a estrutura de nossa API. Vimos como definir metadados, servidores, schemas reutilizáveis, paths e operações com seus parâmetros e respostas.
Ao separar a geração da especificação (generate_spec.py
) da lógica da aplicação (app.py
), criamos um fluxo de trabalho limpo: implemente sua API, então execute o gerador para produzir a documentação. Este processo, embora mais manual do que abordagens baseadas em decoradores, oferece controle e flexibilidade incomparáveis, tornando-o ideal para projetos complexos, bases de código legadas ou quando os padrões de documentação são rigorosos.
Finalmente, ao servir a especificação gerada e uma instância da Swagger UI, fornecemos um portal de documentação polido, profissional e altamente utilizável para os consumidores de nossa API. Agora você tem uma nova e poderosa ferramenta em seu arsenal de desenvolvimento Python para criar documentação de API de classe mundial.
Quer uma plataforma integrada e Tudo-em-Um para sua Equipe de Desenvolvedores trabalhar com produtividade máxima?
Apidog entrega todas as suas demandas, e substitui o Postman por um preço muito mais acessível!
button