Урок курса

Проект FastAPI и первый GET

FastAPI для начинающих: API с базой данных и тестами

В прошлом уроке мы разобрали, как JSON оформляется в теле HTTP-ответа и что означает заголовок Content-Type: application/json. Теперь сделаем шаг от чтения чужих ответов к написанию собственного: создадим проект FastAPI, напишем первый маршрут и получим рабочий ответ 200 с JSON.

Папка проекта, venv и установка пакетов

Прежде всего нужна отдельная папка для проекта. Создайте папку fastapi-demo и откройте в ней терминал.

Виртуальное окружение — это вложенная папка со своим Python-интерпретатором и набором пакетов. Всё, что вы устанавливаете внутри окружения, не попадает в системный Python и не конфликтует с другими проектами. Создаётся одной командой:

python -m venv venv

В папке fastapi-demo появится подпапка venv. Теперь нужно установить в это окружение два пакета: FastAPI и Uvicorn.

FastAPI связывает входящие HTTP-запросы с Python-функциями.

Uvicorn — это сервер: он принимает сетевые соединения и передаёт их приложению.

Вместо того чтобы активировать окружение, можно обратиться к его Python-интерпретатору напрямую. В PowerShell:

.\venv\Scripts\python.exe -m pip install fastapi uvicorn

На macOS/Linux:

venv/bin/python -m pip install fastapi uvicorn

Этот способ работает в PowerShell без изменения политики выполнения скриптов — Activate.ps1 при этом не запускается вовсе.

Если вы всё же хотите активировать окружение (в cmd — venv\Scripts\activate.bat, на macOS/Linux — source venv/bin/activate), команды установки и запуска станут короче: достаточно писать просто python вместо полного пути к интерпретатору.

После установки папка venv/Lib/site-packages (или venv/lib/python3.x/site-packages на macOS/Linux) содержит fastapi и uvicorn. Больше ничего настраивать не нужно.

Файл main.py и объект приложения

Создайте файл main.py прямо в папке fastapi-demo — рядом с папкой venv, а не внутри неё. Структура выглядит так:

fastapi-demo/
├── venv/
└── main.py

В main.py сначала нужен импорт:

from fastapi import FastAPI

Эта строка делает доступным класс FastAPI из установленного пакета. Затем создаём объект приложения:

app = FastAPI()

Здесь FastAPI — класс, FastAPI() — вызов его конструктора, app — переменная, в которой хранится созданный объект. На этом объекте будут регистрироваться маршруты.

Имя переменной app — не магическое слово языка, а просто соглашение. Важно оно при запуске через Uvicorn: запись main:app означает «возьми модуль main (файл main.py без расширения) и найди в нём переменную app». Если назвать переменную application, запись стала бы main:application. Пока используем app — так короче и понятнее.

Декоратор связывает GET с Python-функцией

Чтобы FastAPI знал, какую функцию вызывать при запросе GET /api/rooms, используется декоратор. Декоратор — это строка над функцией, начинающаяся с @. Она передаёт функцию другому коду ещё в момент определения, до любых запросов.

@app.get("/api/rooms") регистрирует в объекте app связь: метод GET плюс путь /api/rooms → функция, которая написана сразу под декоратором. Имя функции при этом не задаёт URL.

Вот полный main.py для каталога переговорных:

from fastapi import FastAPI

app = FastAPI()

@app.get("/api/rooms")
def list_rooms():
    return [{"id": 1, "name": "Лондон", "floor": 2}]

Когда приходит запрос GET /api/rooms, FastAPI вызывает list_rooms(). Функция возвращает обычный Python-список со словарём внутри. FastAPI автоматически сериализует его в JSON и добавляет заголовок Content-Type: application/json. Код ответа по умолчанию — 200.

Путь /api/rooms выбран произвольно для этого примера — никакого особого смысла в FastAPI он не несёт. Можно было написать /rooms или /v1/rooms; декоратор зарегистрирует любую строку пути.

В предыдущем уроке мы разбирали JSON как формат в теле HTTP-ответа. Здесь FastAPI делает эту работу сам: вы возвращаете Python-данные, а список становится JSON-массивом [{"id":1,"name":"Лондон","floor":2}] в теле ответа.

Запись main:app указывает на модуль main.py и объект app. Декоратор app.get связывает GET /api/rooms с list_rooms. Функция возвращает список со словарём; FastAPI преобразует его в JSON-ответ со статусом 200.
main:app выбирает объект app из main.py. Декоратор связывает запрос с функцией, а FastAPI превращает её результат в JSON.

Uvicorn: запуск, reload и остановка

Сохранённый main.py — это просто файл. Сам по себе он не слушает никакой порт и не принимает запросы. Чтобы получить работающий сервер, нужен Uvicorn.

Откройте терминал в папке fastapi-demo (там, где лежит main.py) и выполните:

.\venv\Scripts\python.exe -m uvicorn main:app --reload

На macOS/Linux:

venv/bin/python -m uvicorn main:app --reload

Если окружение активировано, достаточно:

python -m uvicorn main:app --reload

Uvicorn импортирует app из main.py и начинает слушать http://127.0.0.1:8000. В терминале появятся строки вроде:

INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process

Флаг --reload заставляет Uvicorn следить за изменениями файлов. Когда вы сохраните отредактированный main.py, сервер перезапустится автоматически — перезапускать его вручную не придётся.

Терминал занят процессом сервера. Чтобы отправить запрос, откройте браузер и перейдите по адресу:

http://127.0.0.1:8000/api/rooms

Браузер покажет JSON-массив. Если нужно выполнить другие команды в терминале, откройте второй терминал — не останавливайте сервер.

Пока оставьте сервер работающим — он нужен для проверки /docs ниже. Когда закончите проверку, вернитесь в терминал с Uvicorn и нажмите Ctrl+C: сервер завершит работу, порт освободится.

Статус, JSON и заголовки в /docs

При работающем Uvicorn откройте в браузере второй адрес:

http://127.0.0.1:8000/docs

Это Swagger UI — интерактивная страница документации, которую FastAPI строит автоматически на основе зарегистрированных маршрутов. Никаких дополнительных настроек не нужно.

На странице виден маршрут GET /api/rooms. Раскройте его кликом, нажмите Try it out, затем Execute. Swagger UI отправит настоящий HTTP-запрос к вашему серверу и покажет результат прямо на странице.

Вы увидите три вещи:

  • Code — код ответа. Для нашего маршрута это 200.
  • Response body — тело ответа в виде JSON: [{"id": 1, "name": "Лондон", "floor": 2}].
  • Response headers — заголовки, среди которых content-type: application/json.

Это те же данные, что возвращает прямой запрос к /api/rooms в браузере, только в /docs статус и заголовки видны явно — браузер их обычно скрывает.

Задача 1

Какой main.py зарегистрирует GET /api/rooms, после чего маршрут появится в /docs?

Выберите один вариант
Без регистрации · результат не сохраняется

Задача 2

В папке проекта есть только main.py с объектом app; модуля app в проекте нет. Разработчик набрал python -m uvicorn app:main --reload вместо python -m uvicorn main:app --reload. Что произойдёт при загрузке приложения и почему?

Выберите один вариант
Без регистрации · результат не сохраняется

Задача 3

Функция-обработчик FastAPI возвращает Python-список [{"id": 1, "name": "Лондон"}]. Что FastAPI сделает с этим значением перед отправкой клиенту?

Выберите один вариант
Без регистрации · результат не сохраняется

Задача 4

Первый каталог Roomly

Roomly — это внутренний сервис компании, который помогает сотрудникам ориентироваться в пространстве офиса и договариваться о месте для встречи. Прежде чем коллеги смогут выбрать подходящую переговорную, им нужно знать, что вообще доступно: как называется комната и на каком этаже она находится. Именно эту базовую информацию и призван предоставлять первый маршрут сервиса.

Разработка Roomly ведётся постепенно, и каждый новый шаг опирается на уже написанный код. Отправной точкой служит каталог переговорных — компактный список, который приложение возвращает по запросу. Пока в нём нет ни броней, ни фильтров, ни учётных записей: только названия комнат и этажи, достаточные для первого знакомства с пространством.

Когда приложение запущено локально и маршрут каталога зарегистрирован, обращение к нему возвращает JSON-список переговорных. Получить такой ответ — значит убедиться, что фундамент Roomly заложен верно и последующие лабораторные работы будут достраивать именно его.

Что уже дано

В редакторе открыт самодостаточный main.py: импорт FastAPI, объект верхнего уровня app и единый in-memory словарь rooms_by_id уже созданы. В словаре находятся переговорные с полями id, name и floor. Маршрутов и функций-обработчиков пока нет. Перед файлом выполняется видимый служебный переходник проверки: он определяет функции для запросов и чтения состояния, но не создаёт приложение или данные каталога. Менять переходник не нужно.

Что нужно сделать

Самостоятельно зарегистрируйте маршрут для метода GET и точного пути /api/rooms. Напишите функцию-обработчик, которая возвращает JSON-массив всех переговорных из rooms_by_id в порядке словаря. Запрос к маршруту должен получать статус 200. Не добавляйте параметры пути, query-параметры или другие маршруты.

Ввод и вывод

stdin не используется. Печатать через print в stdout ничего не нужно. После вашего кода проверяющая система читает объекты верхнего уровня app и rooms_by_id, затем отправляет запросы к app через TestClient. Результатом служат статус и JSON HTTP-ответа.

РешениеPython

Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.

Отправьте решение, чтобы увидеть результаты тестов.

Задачи к уроку

Все задачи курса →

Продолжить с сохранением прогресса

Перейдите к уроку в учебном кабинете.

Перейти к интерактивному уроку