Поскольку сгенерированная схема соответствует стандарту OpenAPI, её можно использовать со множеством совместимых инструментов.
Именно поэтому, FastAPI сам предоставляет альтернативную документацию API (используя ReDoc), которую можно получить по адресу: http://127.0.0.1:8000/redoc.
По той же причине, есть множество совместимых инструментов, включая инструменты генерации кода для многих языков.
При создании операций пути можно столкнуться с ситуацией, когда путь является фиксированным.
Например, /users/me. Предположим, что это путь для получения данных о текущем пользователе.
У вас также может быть путь /users/{user_id}, чтобы получить данные о конкретном пользователе по его ID.
Поскольку операции пути выполняются в порядке их объявления, необходимо, чтобы путь для /users/me был объявлен раньше, чем путь для /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}
Иначе путь для /users/{user_id} также будет соответствовать /users/me, "подразумевая", что он получает параметр user_id со значением "me".
Аналогично, вы не можете переопределить операцию с путем:
Что если нам нужно заранее определить допустимые параметры пути, которые операция пути может принимать? В таком случае можно использовать стандартное перечисление Enum Python.
Импортируйте Enum и создайте подкласс, который наследуется от str и Enum.
Мы наследуемся от str, чтобы документация API могла понять, что значения должны быть типа string и отображалась правильно.
Затем создайте атрибуты класса с фиксированными допустимыми значениями:
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"}
Определите параметр пути, используя в аннотации типа класс перечисления (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"}
Вы можете сравнить это значение с элементом перечисления класса 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"}
Можно получить фактическое значение (в данном случае - str) с помощью model_name.value или в общем случае 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"}
Подсказка
Значение "lenet" также можно получить с помощью ModelName.lenet.value.
Из операции пути можно вернуть элементы перечисления, даже вложенные в тело JSON (например в dict).
Они будут преобразованы в соответствующие значения (в данном случае - строки) перед их возвратом клиенту:
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"}
OpenAPI не поддерживает способов объявления параметра пути, содержащего внутри путь, так как это может привести к сценариям, которые сложно определять и тестировать.
Тем не менее это можно сделать в FastAPI, используя один из внутренних инструментов Starlette.
Документация по-прежнему будет работать, хотя и не добавит никакой информации о том, что параметр должен содержать путь.