Quando você abrir o seu navegador em http://127.0.0.1:8000/docs, você verá de forma automática e interativa a documentação da API como:
Verifique
Novamente, apenas com a mesma declaração de tipo do Python, o FastAPI te dá de forma automática e interativa a documentação (integrada com o Swagger UI).
Veja que o parâmetro de rota está declarado como sendo um inteiro (int).
Beneficios baseados em padrões, documentação alternativa¶
Devido ao schema gerado ser o padrão do OpenAPI, existem muitas ferramentas compatíveis.
Por esse motivo, o próprio FastAPI fornece uma API alternativa para documentação (utilizando ReDoc), que você pode acessar em http://127.0.0.1:8000/redoc:
Da mesma forma, existem muitas ferramentas compatíveis. Incluindo ferramentas de geração de código para muitas linguagens.
Toda a validação de dados é feita por baixo dos panos pelo Pydantic, então você tem todos os benefícios disso. E assim você sabe que está em boas mãos.
Você pode usar as mesmas declarações de tipo com str, float, bool e muitos outros tipos complexos de dados.
Vamos explorar muitos destes tipos nos próximos capítulos do tutorial.
Quando você cria operações de rota, você pode se deparar com situações onde você pode ter uma rota fixa.
Algo como /users/me por exemplo, digamos que essa rota seja utilizada para pegar dados sobre o usuário atual.
E então você pode ter também uma rota /users/{user_id} para pegar dados sobre um usuário específico associado a um ID de usuário.
Porque as operações de rota são avaliadas em ordem, você precisa ter certeza que a rota para /users/me está sendo declarado antes da rota /users/{user_id}:
fromfastapiimportFastAPIapp=FastAPI()@app.get("/users/me")asyncdefread_user_me():return{"user_id":"the current user"}@app.get("/users/{user_id}")asyncdefread_user(user_id:str):return{"user_id":user_id}
Caso contrário, a rota para /users/{user_id} coincidiria também para /users/me, "pensando" que estaria recebendo o parâmetro user_id com o valor de "me".
Se você tem uma operação de rota que recebe um parâmetro da rota, mas que você queira que esses valores possíveis do parâmetro da rota sejam predefinidos, você pode usar Enum padrão do Python.
Importe Enum e crie uma sub-classe que herde de str e de Enum.
Por herdar de str a documentação da API vai ser capaz de saber que os valores devem ser do tipo string e assim ser capaz de mostrar eles corretamente.
Assim, crie atributos de classe com valores fixos, que serão os valores válidos disponíveis.
fromenumimportEnumfromfastapiimportFastAPIclassModelName(str,Enum):alexnet="alexnet"resnet="resnet"lenet="lenet"app=FastAPI()@app.get("/models/{model_name}")asyncdefget_model(model_name:ModelName):ifmodel_nameisModelName.alexnet:return{"model_name":model_name,"message":"Deep Learning FTW!"}ifmodel_name.value=="lenet":return{"model_name":model_name,"message":"LeCNN all the images"}return{"model_name":model_name,"message":"Have some residuals"}
Logo, crie um parâmetro de rota com anotações de tipo usando a classe enum que você criou (ModelName):
fromenumimportEnumfromfastapiimportFastAPIclassModelName(str,Enum):alexnet="alexnet"resnet="resnet"lenet="lenet"app=FastAPI()@app.get("/models/{model_name}")asyncdefget_model(model_name:ModelName):ifmodel_nameisModelName.alexnet:return{"model_name":model_name,"message":"Deep Learning FTW!"}ifmodel_name.value=="lenet":return{"model_name":model_name,"message":"LeCNN all the images"}return{"model_name":model_name,"message":"Have some residuals"}
Visto que os valores disponíveis para o parâmetro da rota estão predefinidos, a documentação interativa pode mostrar esses valores de uma forma bem legal:
Você pode comparar eles com o membro de enumeration no enum ModelName que você criou:
fromenumimportEnumfromfastapiimportFastAPIclassModelName(str,Enum):alexnet="alexnet"resnet="resnet"lenet="lenet"app=FastAPI()@app.get("/models/{model_name}")asyncdefget_model(model_name:ModelName):ifmodel_nameisModelName.alexnet:return{"model_name":model_name,"message":"Deep Learning FTW!"}ifmodel_name.value=="lenet":return{"model_name":model_name,"message":"LeCNN all the images"}return{"model_name":model_name,"message":"Have some residuals"}
Você pode ter o valor exato de enumerate (um str nesse caso) usando model_name.value, ou em geral, your_enum_member.value:
fromenumimportEnumfromfastapiimportFastAPIclassModelName(str,Enum):alexnet="alexnet"resnet="resnet"lenet="lenet"app=FastAPI()@app.get("/models/{model_name}")asyncdefget_model(model_name:ModelName):ifmodel_nameisModelName.alexnet:return{"model_name":model_name,"message":"Deep Learning FTW!"}ifmodel_name.value=="lenet":return{"model_name":model_name,"message":"LeCNN all the images"}return{"model_name":model_name,"message":"Have some residuals"}
Dica
Você também poderia acessar o valor "lenet" com ModelName.lenet.value
Você pode retornar membros de enum da sua rota de operação, em um corpo JSON aninhado (por exemplo um dict).
Eles serão convertidos para o seus valores correspondentes (strings nesse caso) antes de serem retornados ao cliente:
fromenumimportEnumfromfastapiimportFastAPIclassModelName(str,Enum):alexnet="alexnet"resnet="resnet"lenet="lenet"app=FastAPI()@app.get("/models/{model_name}")asyncdefget_model(model_name:ModelName):ifmodel_nameisModelName.alexnet:return{"model_name":model_name,"message":"Deep Learning FTW!"}ifmodel_name.value=="lenet":return{"model_name":model_name,"message":"LeCNN all the images"}return{"model_name":model_name,"message":"Have some residuals"}
No seu cliente você vai obter uma resposta JSON como:
O OpenAPI não suporta uma maneira de declarar um parâmetro de rota que contenha uma rota dentro, dado que isso poderia levar a cenários que são difíceis de testar e definir.
No entanto, você pode fazer isso no FastAPI, usando uma das ferramentas internas do Starlette.
A documentação continuaria funcionando, ainda que não adicionaria nenhuma informação dizendo que o parâmetro deveria conter uma rota.