19 KiB
Користувацька відповідь - HTML, стрім, файл, інше
Типово FastAPI повертатиме відповіді, використовуючи JSONResponse.
Ви можете переписати це, повернувши безпосередньо Response, як показано в Повернути відповідь безпосередньо{.internal-link target=_blank}.
Але якщо ви повертаєте Response безпосередньо (або будь-який його підклас, як-от JSONResponse), дані не будуть автоматично конвертовані (навіть якщо ви оголосите response_model), і документація не буде автоматично згенерована (наприклад, із включенням конкретного «медіа-типу» в HTTP-заголовку Content-Type як частини згенерованого OpenAPI).
Ви також можете оголосити Response, який слід використовувати (наприклад, будь-який підклас Response), у декораторі операції шляху через параметр response_class.
Вміст, який ви повертаєте з вашої функції операції шляху, буде поміщений усередину цього Response.
І якщо цей Response має JSON медіа-тип (application/json), як у випадку з JSONResponse та UJSONResponse, дані, що повертаються, будуть автоматично перетворені (і відфільтровані) з урахуванням будь-якого Pydantic response_model, який ви оголосили в декораторі операції шляху.
/// note | Примітка
Якщо ви використовуєте клас відповіді без медіа-типу, FastAPI очікуватиме, що у вашої відповіді не буде вмісту, тож формат відповіді не буде задокументовано в згенерованих OpenAPI-документах.
///
Використовуйте ORJSONResponse
Наприклад, якщо ви максимально оптимізуєте продуктивність, можете встановити та використовувати orjson і встановити відповідь як ORJSONResponse.
Імпортуйте потрібний клас Response (підклас) і оголосіть його в декораторі операції шляху.
Для великих відповідей повернення Response безпосередньо значно швидше, ніж повернення словника.
Це тому, що за замовчуванням FastAPI перевірятиме кожен елемент усередині та переконуватиметься, що його можна серіалізувати як JSON, використовуючи той самий Сумісний кодувальник JSON{.internal-link target=_blank}, описаний у навчальному посібнику. Саме це дозволяє повертати довільні об'єкти, наприклад моделі бази даних.
Але якщо ви впевнені, що вміст, який повертається, серіалізується в JSON, ви можете передати його безпосередньо класу відповіді та уникнути додаткових витрат FastAPI на пропускання вашого вмісту через jsonable_encoder перед передаванням його класу відповіді.
{* ../../docs_src/custom_response/tutorial001b_py310.py hl[2,7] *}
/// info | Інформація
Параметр response_class також визначатиме «медіа-тип» відповіді.
У цьому випадку HTTP-заголовок Content-Type буде встановлено в application/json.
І це буде задокументовано відповідно в OpenAPI.
///
/// tip | Порада
ORJSONResponse доступний лише у FastAPI, не в Starlette.
///
HTML-відповідь
Щоб повернути відповідь із HTML безпосередньо з FastAPI, використовуйте HTMLResponse.
- Імпортуйте
HTMLResponse. - Передайте
HTMLResponseяк параметрresponse_classвашого декоратора операції шляху.
{* ../../docs_src/custom_response/tutorial002_py310.py hl[2,7] *}
/// info | Інформація
Параметр response_class також визначатиме «медіа-тип» відповіді.
У цьому випадку HTTP-заголовок Content-Type буде встановлено в text/html.
І це буде задокументовано відповідно в OpenAPI.
///
Повернути Response
Як показано в Повернути відповідь безпосередньо{.internal-link target=_blank}, ви також можете переписати відповідь безпосередньо у вашій операції шляху, просто повернувши її.
Той самий приклад вище, що повертає HTMLResponse, може виглядати так:
{* ../../docs_src/custom_response/tutorial003_py310.py hl[2,7,19] *}
/// warning | Попередження
Response, повернений безпосередньо вашою функцією операції шляху, не буде задокументовано в OpenAPI (наприклад, Content-Type не буде задокументовано) і не буде видно в автоматичній інтерактивній документації.
///
/// info | Інформація
Звісно, фактичні заголовок Content-Type, код статусу тощо прийдуть з об'єкта Response, який ви повернули.
///
Задокументуйте в OpenAPI і перепишіть Response
Якщо ви хочете переписати відповідь усередині функції, але водночас задокументувати «медіа-тип» в OpenAPI, ви можете використати параметр response_class І повернути об'єкт Response.
Тоді response_class буде використано лише для документування операції шляху в OpenAPI, а ваша Response буде використана як є.
Повернути HTMLResponse безпосередньо
Наприклад, це може бути щось на кшталт:
{* ../../docs_src/custom_response/tutorial004_py310.py hl[7,21,23] *}
У цьому прикладі функція generate_html_response() уже генерує та повертає Response замість повернення HTML як str.
Повертаючи результат виклику generate_html_response(), ви вже повертаєте Response, яка перепише типову поведінку FastAPI.
Але оскільки ви також передали HTMLResponse у response_class, FastAPI знатиме, як задокументувати це в OpenAPI та інтерактивній документації як HTML з text/html:
Доступні відповіді
Ось деякі з доступних відповідей.
Майте на увазі, що ви можете використовувати Response, щоб повертати що завгодно інше, або навіть створити власний підклас.
/// note | Технічні деталі
Ви також можете використати from starlette.responses import HTMLResponse.
FastAPI надає ті ж starlette.responses як fastapi.responses лише для вашої зручності як розробника. Але більшість доступних відповідей надходять безпосередньо зі Starlette.
///
Response
Головний клас Response, від якого успадковуються всі інші відповіді.
Ви можете повертати його безпосередньо.
Він приймає такі параметри:
content-strабоbytes.status_code-int- код статусу HTTP.headers-dictстрок.media_type-str, що задає медіа-тип, напр."text/html".
FastAPI (насправді Starlette) автоматично додасть заголовок Content-Length. Також буде додано заголовок Content-Type, на основі media_type з додаванням набору символів для текстових типів.
{* ../../docs_src/response_directly/tutorial002_py310.py hl[1,18] *}
HTMLResponse
Приймає текст або байти та повертає HTML-відповідь, як описано вище.
PlainTextResponse
Приймає текст або байти та повертає відповідь звичайним текстом.
{* ../../docs_src/custom_response/tutorial005_py310.py hl[2,7,9] *}
JSONResponse
Приймає дані та повертає відповідь, закодовану як application/json.
Це типова відповідь, яку використовує FastAPI, як зазначено вище.
ORJSONResponse
Швидка альтернативна JSON-відповідь з використанням orjson, як описано вище.
/// info | Інформація
Потрібно встановити orjson, наприклад pip install orjson.
///
UJSONResponse
Альтернативна JSON-відповідь з використанням ujson.
/// info | Інформація
Потрібно встановити ujson, наприклад pip install ujson.
///
/// warning | Попередження
ujson менш обережний, ніж вбудована реалізація Python, у поводженні з деякими крайніми випадками.
///
{* ../../docs_src/custom_response/tutorial001_py310.py hl[2,7] *}
/// tip | Порада
Ймовірно, ORJSONResponse може бути швидшою альтернативою.
///
RedirectResponse
Повертає HTTP-перенаправлення. Типово використовує код статусу 307 (Temporary Redirect).
Ви можете повернути RedirectResponse безпосередньо:
{* ../../docs_src/custom_response/tutorial006_py310.py hl[2,9] *}
Або ви можете використати його в параметрі response_class:
{* ../../docs_src/custom_response/tutorial006b_py310.py hl[2,7,9] *}
У такому разі ви можете повертати URL безпосередньо з вашої функції операції шляху.
У цьому випадку status_code буде типовим для RedirectResponse, тобто 307.
Ви також можете використати параметр status_code разом із параметром response_class:
{* ../../docs_src/custom_response/tutorial006c_py310.py hl[2,7,9] *}
StreamingResponse
Приймає async-генератор або звичайний генератор/ітератор і транслює тіло відповіді потоково.
{* ../../docs_src/custom_response/tutorial007_py310.py hl[2,14] *}
Використання StreamingResponse з об'єктами типу file-like
Якщо у вас є file-like об'єкт (наприклад, об'єкт, що повертається open()), ви можете створити генераторну функцію для ітерації по цьому file-like об'єкту.
Таким чином, вам не потрібно спочатку читати все в пам'ять, і ви можете передати цю генераторну функцію в StreamingResponse і повернути її.
Сюди входить багато бібліотек для взаємодії з хмарними сховищами, обробки відео та інші.
{* ../../docs_src/custom_response/tutorial008_py310.py hl[2,10:12,14] *}
-
Це генераторна функція. Вона є «генераторною функцією», бо містить оператори
yieldусередині. -
Використовуючи блок
with, ми гарантуємо, що file-like об'єкт буде закрито після завершення роботи генераторної функції. Тобто після того, як вона завершить надсилання відповіді. -
Цей
yield fromвказує функції ітеруватися по об'єкту з назвоюfile_like. А потім, для кожної ітерованої частини, повертати цю частину, ніби вона надходить з цієї генераторної функції (iterfile).Тож це генераторна функція, яка всередині передає роботу «генерації» чомусь іншому.
Роблячи це таким чином, ми можемо помістити її в блок
withі таким чином гарантувати, що file-like об'єкт буде закрито після завершення.
/// tip | Порада
Зверніть увагу, що тут ми використовуємо стандартний open(), який не підтримує async та await, тому ми оголошуємо операцію шляху звичайною def.
///
FileResponse
Асинхронно транслює файл як відповідь.
Приймає інший набір аргументів для створення екземпляра, ніж інші типи відповідей:
path- шлях до файлу для трансляції.headers- будь-які користувацькі заголовки як словник.media_type- строка, що задає медіа-тип. Якщо не встановлено, медіа-тип буде виведено з імені файлу або шляху.filename- якщо встановлено, буде включено доContent-Dispositionвідповіді.
Відповіді з файлами включатимуть відповідні заголовки Content-Length, Last-Modified і ETag.
{* ../../docs_src/custom_response/tutorial009_py310.py hl[2,10] *}
Ви також можете використати параметр response_class:
{* ../../docs_src/custom_response/tutorial009b_py310.py hl[2,8,10] *}
У цьому випадку ви можете повертати шлях до файлу безпосередньо з вашої функції операції шляху.
Власний клас відповіді
Ви можете створити власний клас відповіді, успадкувавши його від Response, і використовувати його.
Наприклад, скажімо, ви хочете використовувати orjson, але з деякими користувацькими налаштуваннями, які не використовуються у вбудованому класі ORJSONResponse.
Припустімо, ви хочете, щоб повертався відформатований із відступами JSON, тож ви хочете використати опцію orjson orjson.OPT_INDENT_2.
Ви можете створити CustomORJSONResponse. Головне, що потрібно зробити, це створити метод Response.render(content), який повертає вміст як bytes:
{* ../../docs_src/custom_response/tutorial009c_py310.py hl[9:14,17] *}
Тепер замість повернення:
{"message": "Hello World"}
...ця відповідь повертатиме:
{
"message": "Hello World"
}
Звісно, ви, ймовірно, знайдете значно кращі способи скористатися цим, ніж просто форматування JSON. 😉
Типова відповідь за замовчуванням
Створюючи екземпляр класу FastAPI або APIRouter, ви можете вказати, який клас відповіді використовувати за замовчуванням.
Параметр, що це визначає, - default_response_class.
У прикладі нижче FastAPI використовуватиме ORJSONResponse за замовчуванням в усіх операціях шляху замість JSONResponse.
{* ../../docs_src/custom_response/tutorial010_py310.py hl[2,4] *}
/// tip | Порада
Ви все одно можете переписати response_class в операціях шляху, як і раніше.
///
Додаткова документація
Ви також можете оголосити медіа-тип і багато інших деталей в OpenAPI, використовуючи responses: Додаткові відповіді в OpenAPI{.internal-link target=_blank}.