Esta lib é capaz de nos dar recursos muito uteis para se trabalhar no desenvolvimento de APIRest. A flask_smorest pode unir o desenvolvimento da API já com uma documentação integrada ao Swagger. Dentre os beneficios de se usa-la estão:
- Blueprint ( para modularização do código )
- Marshmallow ( para criação de schemas e validação dos dados )
- Swagger ( para documentação do código da API de forma automatizada )
- abort ( para mensagens de retorno com status_code e um retorno em JSON da mensagem.)
O primeiro passo para modularização é separar o codigo de rotas em arquivos. Neste curso estamos fazendo a criação de itens e lojas então separar cada um em um modulo torna mais organizado.
Depois disto o que se resta fazer é importar a lib Blueprint do flask-smorest (não do Flask) e usar o MethodView de flask.views para estender uma classe que vai conter os metodos de interatividade da API
from flask.views import MethodView
from flask_smorest import Blueprint
from db import stores
blp = Blueprint('store', __name__, description='Operations in stores')
@blp.route('/store)
class Store(MethodView):
def get(self):
return stores
def post(self, store_data):
...
return store_data
Após fazer esta modularização é importante ir até o arquivo principal (app.py) e então fazer a importação da Api que faz parte do módulo do flasksmorest. Ela vai enfeitar o nosso app ( de Flask(name) ) nos retornando um objeto com um metodo _register_blueprint para inserirmos os nossos Blueprints. Para já ter uma documentação com o Swagger você deve passar parametros de configuração para o app por meio de app.config.
...
from flask_smorest import Api
from resources.item import blp as ItemBlueprint
from resources.stores import blp as StoreBlueprint
app = Flask(__name__)
# Se acontecer algum erro em uma integração propagar até o App principal
app.config['PROPAGATE_EXCEPTIONS'] = True
app.config['API_TITLE'] = 'Stores Rest API' #Titulo da api
app.config['API_VERSION'] = "v1" # Versao da API
app.config['OPENAPI_VERSION'] = "3.0.3" # Versão do openapi
app.config['OPENAPI_URL_PREFIX'] = "/" # Em qual url de inicio a documentação vai se manifestar
app.config['OPENAPI_SWAGGER_UI_PATH'] = "/swagger-ui" # http://localhost:5005/swagger-ui
app.config['OPENAPI_SWAGGER_UI_URL'] = 'https://cdn.jsdelivr.net/npm/swagger-ui-dist/'
api = Api(app)
api.register_blueprint(ItemBlueprint)
api.register_blueprint(StoreBlueprint)
A forma sensacional como esta documentação é disposta na tela e a simplicidade de integração assusta. Com isto a sua APIRest já tem documentação swagger descrevendo todos os módulos, isto é uma maravilha.
O marshmallow é uma lib usada para criar schemas e validar dados para que eles tenham a mesma estrutura que se espera receber/devolver na API. Para usa-lo é interessante criar um arquivo que vai concentrar todos os schemas, o nome deste arquivo pode ser schemas.py. Com o arquivo criado agora você basicamente precisa importar fields e Schema.
from marshmallow import fields, Schema
class ItemSchema(Schema):
id = fields.Str(dump_only=True)
Um detalhe importante é fields, ele é capaz de passar vários tipos de validadores de campos os mais comuns são:
- fields.Str (para strings)
- fields.Float (para números de ponto flutuante)
- fields.Int (para inteiros)
- fields.List (para listas de dados)
- fields.Enum (para enumeração de opções)
As opções são muitas, o ideal é ver a doc. Alguns dos argumentos que podem ser passados na instanciação de um validador de campo são.
- dump_only (diz que este campo só será validado e retornado na resposta ao cliente)
- required ( quando marcado como True exige que este campo esteja contido tanto na entrada quanto na saida.)
Depois de criado os schemas pode-se fazer uso deles inserindo nas chamadas por meio do decorador arguments do Blueprint.
# Exemplo 1
@blp.arguments(ItemUpdateSchema)
def put(self, item_id):
...
Só com isto já se tem um validador de campos restringindo o que será enviado pelos clientes e validando todos os dados ali passados.
Outra forma interessante é usar o decorador response para dizer quais os dados que serão retornados na resposta ao cliente.
# Exemplo 2
@blp.arguments(ItemUpdateSchema)
@blp.response(200, ItemSchema)
def put(self, item_data, item_id):
...
Veja que neste exemplo 2 temos a _@blp.response(200, ItemSchema)_ dizendo que o retorno será 200 e o que será retornado será o ItemSchema. Isto vai ajudar também a API do Swagger a gerar a documentação correta sobre o que é enviado e o que é retornado.
- flask-rq2 ou rq para fila de tarefas em background dentro do Flask