Utilizando o nome da função de operação de rota como o operationId¶
Se você quiser utilizar o nome das funções da sua API como operationIds, você pode iterar sobre todos esses nomes e sobrescrever o operationId em cada operação de rota utilizando o APIRoute.name dela.
Você deve fazer isso depois de adicionar todas as suas operações de rota.
fromfastapiimportFastAPIfromfastapi.routingimportAPIRouteapp=FastAPI()@app.get("/items/")asyncdefread_items():return[{"item_id":"Foo"}]defuse_route_names_as_operation_ids(app:FastAPI)->None:""" Simplify operation IDs so that generated API clients have simpler function names. Should be called only after all routes have been added. """forrouteinapp.routes:ifisinstance(route,APIRoute):route.operation_id=route.name# in this case, 'read_items'use_route_names_as_operation_ids(app)
Dica
Se você chamar app.openapi() manualmente, os operationIds devem ser atualizados antes dessa chamada.
Aviso
Se você fizer isso, você tem que ter certeza de que cada uma das suas funções de operação de rota tem um nome único.
Mesmo que elas estejam em módulos (arquivos Python) diferentes.
Para excluir uma operação de rota do esquema OpenAPI gerado (e por consequência, dos sistemas de documentação automáticos), utilize o parâmetro include_in_schema e defina ele como False:
Você pode limitar as linhas utilizadas a partir de uma docstring de uma função de operação de rota para o OpenAPI.
Adicionar um \f (um caractere de escape para alimentação de formulário) faz com que o FastAPI restrinja a saída utilizada pelo OpenAPI até esse ponto.
Ele não será mostrado na documentação, mas outras ferramentas (como o Sphinx) serão capazes de utilizar o resto do texto.
fromtypingimportSet,UnionfromfastapiimportFastAPIfrompydanticimportBaseModelapp=FastAPI()classItem(BaseModel):name:strdescription:Union[str,None]=Noneprice:floattax:Union[float,None]=Nonetags:Set[str]=set()@app.post("/items/",response_model=Item,summary="Create an item")asyncdefcreate_item(item:Item):""" Create an item with all the information: - **name**: each item must have a name - **description**: a long description - **price**: required - **tax**: if the item doesn't have tax, you can omit this - **tags**: a set of unique tag strings for this item \f :param item: User input. """returnitem
Quando você declara uma operação de rota na sua aplicação, o FastAPI irá gerar os metadados relevantes da operação de rota automaticamente para serem incluídos no esquema do OpenAPI.
Se você abrir os documentos criados automaticamente para a API, sua extensão aparecerá no final da operação de rota específica.
E se você olhar o esquema OpenAPI resultante (na rota /openapi.json da sua API), você verá que a sua extensão também faz parte da operação de rota específica:
Esquema de operação de rota do OpenAPI personalizado¶
O dicionário em openapi_extra vai ter todos os seus níveis mesclados dentro do esquema OpenAPI gerado automaticamente para a operação de rota.
Então, você pode adicionar dados extras para o esquema gerado automaticamente.
Por exemplo, você poderia optar por ler e validar a requisição com seu próprio código, sem utilizar funcionalidades automatizadas do FastAPI com o Pydantic, mas você ainda pode quere definir a requisição no esquema OpenAPI.
Você pode fazer isso com openapi_extra:
fromfastapiimportFastAPI,Requestapp=FastAPI()defmagic_data_reader(raw_body:bytes):return{"size":len(raw_body),"content":{"name":"Maaaagic","price":42,"description":"Just kiddin', no magic here. ✨",},}@app.post("/items/",openapi_extra={"requestBody":{"content":{"application/json":{"schema":{"required":["name","price"],"type":"object","properties":{"name":{"type":"string"},"price":{"type":"number"},"description":{"type":"string"},},}}},"required":True,},},)asyncdefcreate_item(request:Request):raw_body=awaitrequest.body()data=magic_data_reader(raw_body)returndata
Nesse exemplo, nós não declaramos nenhum modelo do Pydantic. Na verdade, o corpo da requisição não está nem mesmo analisado como JSON, ele é lido diretamente como bytes e a função magic_data_reader() seria a responsável por analisar ele de alguma forma.
De toda forma, nós podemos declarar o esquema esperado para o corpo da requisição.
Utilizando esse mesmo truque, você pode utilizar um modelo Pydantic para definir o esquema JSON que é então incluído na seção do esquema personalizado do OpenAPI na operação de rota.
E você pode fazer isso até mesmo quando os dados da requisição não seguem o formato JSON.
Por exemplo, nesta aplicação nós não usamos a funcionalidade integrada ao FastAPI de extrair o esquema JSON dos modelos Pydantic nem a validação automática do JSON. Na verdade, estamos declarando o tipo do conteúdo da requisição como YAML, em vez de JSON:
Na versão 1 do Pydantic, o método para obter o esquema JSON de um modelo é Item.schema(), na versão 2 do Pydantic, o método é Item.model_json_schema()
Entretanto, mesmo que não utilizemos a funcionalidade integrada por padrão, ainda estamos usando um modelo Pydantic para gerar um esquema JSON manualmente para os dados que queremos receber no formato YAML.
Então utilizamos a requisição diretamente, e extraímos o corpo como bytes. Isso significa que o FastAPI não vai sequer tentar analisar o corpo da requisição como JSON.
E então no nosso código, nós analisamos o conteúdo YAML diretamente, e estamos utilizando o mesmo modelo Pydantic para validar o conteúdo YAML:
Na versão 1 do Pydantic, o método para analisar e validar um objeto era Item.parse_obj(), na versão 2 do Pydantic, o método é chamado de Item.model_validate().
Dica
Aqui reutilizamos o mesmo modelo do Pydantic.
Mas da mesma forma, nós poderíamos ter validado de alguma outra forma.