Перейти к содержанию

172 уроков, 13 библиотек и челлендж «Что выведет код?» — бесплатно, код прямо в браузере

Начать обучение
Урок 1 из 10 Начальный 35 мин 100 XP

Что такое API и REST: введение в FastAPI для начинающих

Понять, что такое API, REST, HTTP-методы и JSON — и подготовиться к первому приложению на FastAPI.

Редакция Питоники

Представьте: вы написали на Python скрипт, который считает выручку кофейни за день. Скрипт лежит у вас на ноутбуке. А менеджеру нужны эти цифры в его мобильном приложении, курьеру — в его системе, аналитику — в дашборде. Три человека, три устройства, один набор данных. Рассылать каждому Excel по почте — тупик. Выход один: поднять сервер, который по запросу отдаёт данные в аккуратном виде. Такой сервер и называется API — и весь этот курс мы будем строить его на FastAPI, самом быстрорастущем веб-фреймворке Python.

Этот урок — фундамент. Без него дальше будет туман: вы сможете копировать код из документации, но не поймёте, почему он работает. А с фундаментом вы будете видеть за каждой строчкой кода обычный HTTP-запрос. Поехали.

Что такое API простыми словами

API (Application Programming Interface, программный интерфейс приложения) — это набор правил, по которым одна программа может попросить другую программу сделать что-то или отдать данные. Ключевое слово здесь — «попросить», а не «залезть внутрь». API — это договор о том, какие запросы можно делать и что вы получите в ответ.

Классическая метафора — официант в ресторане. Вы (клиент) не заходите на кухню (сервер) и не сами варите борщ. Вы говорите официанту: «Один борщ» — он передаёт заказ на кухню и приносит готовое. Меню — это и есть API-документация: список блюд (эндпоинтов), которые кухня готова готовить. Если вы попросите то, чего нет в меню, официант не станет угадывать — он откажет.

Метафора хороша для старта, но живой разработчик должен видеть за ней технику. Когда мобильное приложение «Кофе у дома» показывает вам меню, оно не хранит напитки внутри себя. Оно отправляет HTTP-запрос на адрес вроде https://api.coffee.ru/products и получает обратно ответ в формате JSON. Сервер при этом может быть написан на чём угодно: Python, Go, Java — клиенту всё равно, потому что договор (API) не меняется. Именно такой сервер вы и научитесь писать на FastAPI.

Клиент и сервер: кто с кем разговаривает

В любой работе с API участвуют две стороны. Клиент — тот, кто отправляет запрос: браузер, мобильное приложение, другой сервер, ваш Python-скрипт или консольная утилита curl. Сервер — тот, кто запрос получает, обрабатывает и возвращает ответ. Это называется клиент-серверной архитектурой, и это первая из шести архитектурных черт, которые вместе образуют стиль REST.

Важно, что клиент и сервер ничего не знают о внутренностях друг друга. Фронтендеру, который рисует каталог товаров, не нужно знать, что за база данных у вас — PostgreSQL или просто список в памяти. Ему важно одно: отправить правильный запрос на правильный адрес и получить правильный JSON. Это разделение — причина, по которой API живут десятилетиями, пока приложения вокруг них переписывают по три раза.

Как выглядит HTTP-запрос изнутри

HTTP — протокол, язык, на котором клиент и сервер ведут переписку. Запрос — это обычный текст, и его можно показать целиком. Вот что отправляет клиент, когда хочет узнать информацию о товаре с номером 42:

HTTP-запрос клиента (как он выглядит на самом деле)
GET /products/42 HTTP/1.1
Host: coffee.example.com
Accept: application/json
Это сырой текст сетевого запроса, а не код Python — в браузере его не запустить. Но скоро вы будете читать такие строки свободно.

Разберём по косточкам. Первая строка — самая важная. GET — это HTTP-метод, действие, которое клиент просит выполнить. /products/42 — путь, то есть какой ресурс интересует. HTTP/1.1 — версия протокола. Дальше идут заголовки (Host, Accept) — служебная информация: кому адресован запрос и в каком формате клиент хочет ответ. У запроса может быть и тело — например, у POST-запроса «создать товар» в теле лежат данные нового товара.

Запомните эту четвёрку: метод, путь, заголовки, тело. Любая веб-разработка — это всего лишь их комбинации. FastAPI всю первую половину курса учит вас именно ими управлять.

Ответ сервера: статус, заголовки и тело

Сервер отвечает в таком же текстовом формате:

HTTP-ответ сервера
HTTP/1.1 200 OK
Content-Type: application/json

{"id": 42, "name": "Эспрессо", "price": 199.9}
Пример реального ответа сервера. Сервер в браузере не запустить — это ожидаемый вывод живого кода FastAPI, который мы напишем во втором уроке.

Первая строка ответа — статус-код с человеческой подписью. 200 OK означает «всё получилось, вот данные». Тело ответа — JSON с данными о товаре. Заголовок Content-Type: application/json честно предупреждает: внутри JSON, а не HTML. Клиент по этому заголовку понимает, как разбирать тело.

HTTP-методы: глаголы, на которых работает REST

Если путь отвечает на вопрос «с чем работаем», то метод — «что делаем». В REST четыре главных метода, и вы будете пользоваться ими каждый день:

МетодЧто делаетПример
GETЧитает данные, ничего не меняетGET /products — список товаров
POSTСоздаёт новый ресурсPOST /products — добавить товар
PUTОбновляет ресурс целикомPUT /products/42 — заменить данные товара
DELETEУдаляет ресурсDELETE /products/42 — убрать товар

Заметьте: чтобы удалить товар с номером 42, клиент отправляет DELETE на путь /products/42, а не на /deleteProduct42. Действие закодировано в методе, а не в адресе. Это непривычно после процедурного программирования, где у вас были функции create_user() и delete_user(), но именно так устроен REST — и на собеседованиях любят спрашивать, почему.

У GET тела нет — читать нечего передавать. А вот POST-запрос несёт данные нового ресурса прямо в теле, сразу после заголовков:

POST-запрос с телом: создаём товар
POST /products HTTP/1.1
Host: coffee.example.com
Content-Type: application/json

{"name": "Латте", "price": 250}
Сырой HTTP-запрос, а не код Python — сетевые запросы в браузерном интерпретаторе не выполняются. Мы напишем настоящий POST-эндпоинт в пятом уроке про CRUD.

Ресурсы и URL: как думать как REST-дизайнер

Ресурс — это любая сущность, с которой работает ваш API: товар, заказ, пользователь, фотография. Каждый ресурс получает свой URL, и URL строят как существительные во множественном числе. Хорошо спроектированный API читается как обычная фраза:

  • GET /products — «покажи товары»
  • GET /orders/17 — «покажи заказ номер 17»
  • GET /users/5/orders — «покажи заказы пользователя номер 5»
  • POST /products — «создай товар» (данные нового товара — в теле запроса)

Коды ответов: 2xx, 4xx, 5xx

Статус-код — первая строка ответа, три числа, которые говорят о результате одним взглядом. Первая цифра — класс: 2xx — успех, 3xx — перенаправление, 4xx — виноват клиент, 5xx — виноват сервер. Половина багов в API находится именно по коду ответа, поэтому вот таблица кодов, которые вы будете видеть чаще всего:

КодНазваниеКогда возникает
200OKОбычный успешный ответ на GET, PUT, DELETE
201CreatedРесурс успешно создан — правильный ответ на POST
204No ContentУспех без тела ответа — так отвечает DELETE
404Not FoundРесурса по этому пути не существует
422Unprocessable EntityДанные в запросе не прошли валидацию
500Internal Server ErrorОшибка в вашем коде на сервере

Код 422 заслуживает отдельного внимания: FastAPI возвращает его, когда прислали кривые данные — например, цену словом «дорого» вместо числа. Это фирменный признак фреймворка: валидация встроена в него так глубоко, что битые запросы отсекаются ещё до вашего кода. В третьем и четвёртом уроках мы будем ловить 422 вживую и учиться читать его структуру.

JSON: язык, на котором говорят все API

JSON (JavaScript Object Notation) — текстовый формат данных, который серверы отдают почти в каждом ответе REST API. Он компактен, читается человеком и парсится любым языком программирования. Выглядит так: {"name": "Эспрессо", "price": 199.9} — объект в фигурных скобках, ключи в двойных кавычках, значения — строки, числа, true/false, null, массивы или вложенные объекты.

В Python есть встроенный модуль json, который превращает словари в JSON-строки (сериализация) и обратно (десериализация). Это не FastAPI — это стандартная библиотека, и она работает прямо в нашем интерактивном редакторе. Попробуйте:

Сериализация: словарь Python превращается в JSON
import json

# Данные товара, как их хранит Python
product = {"id": 42, "name": "Эспрессо", "price": 199.9}

# Сериализация: Python -> строка JSON
as_json = json.dumps(product, ensure_ascii=False)
print(as_json)
print(type(as_json).__name__)
Вывод
{"id": 42, "name": "Эспрессо", "price": 199.9}
str

Обратите внимание на тип: после json.dumps у вас уже не словарь, а строка. Именно она летит по сети. Параметр ensure_ascii=False разрешает кириллицу в читаемом виде — без него «Эспрессо» превратилось бы в Эспрессо, и это тоже валидный JSON, просто глазам больно.

Обратная операция — json.loads: из строки, которую прислал сервер, получается питоновский объект. Важно следить, какие типы JSON даёт на выходе: false становится False, null — None, а целое и дробное число различаются:

Десериализация: строка JSON превращается в объект Python
import json

# Строка, которую прислал сервер
raw = '{"city": "Москва", "temp": 12, "rain": false, "wind": null}'

data = json.loads(raw)
print(data["city"], data["temp"])
print("rain:", data["rain"], "тип:", type(data["rain"]).__name__)
print("wind:", data["wind"], "тип:", type(data["wind"]).__name__)
print("всего ключей:", len(data))
Вывод
Москва 12
rain: False тип: bool
wind: None тип: NoneType
всего ключей: 4

Реальные ответы API почти всегда вложены: заказ содержит список позиций, позиция — ссылку на товар. JSON справляется с этим без усилий — объекты и массивы вкладываются на любую глубину:

Вложенные данные: массивы и объекты внутри JSON
import json

# Заказ: есть вложенные данные - список позиций
order = {
    "id": 17,
    "customer": "Анна",
    "items": ["Эспрессо", "Круассан"],
    "total": 349.9,
}

raw = json.dumps(order, ensure_ascii=False)
print(raw)
print("позиций в заказе:", len(json.loads(raw)["items"]))
Вывод
{"id": 17, "customer": "Анна", "items": ["Эспрессо", "Круассан"], "total": 349.9}
позиций в заказе: 2

FastAPI делает обе операции за вас автоматически: вы возвращаете из функции словарь — клиент получает JSON; клиент присылает JSON — вам в функцию приходит готовый объект. Но понимать, что происходит под капотом, необходимо: когда однажды в ответе окажется не то поле, вы будете искать проблему не там, где она кажется.

Заглянем под капот чуть глубже. Что вообще делает веб-фреймворк, получив запрос? Он разбирает первую строку, достаёт путь и параметры и решает, какую вашу функцию вызвать. Для простого GET-запроса это буквально пара split и partition:

Что FastAPI делает с первой строкой запроса (имитация)
# Имитация разбора первой строки HTTP-запроса,
# которую выполняет любой веб-фреймворк
line = "GET /products?limit=5 HTTP/1.1"

method, path_and_query, protocol = line.split(" ")
path, _, query = path_and_query.partition("?")

print("Метод:", method)
print("Путь:", path)
print("Query-параметры:", query)
print("Протокол:", protocol)
Вывод
Метод: GET
Путь: /products
Query-параметры: limit=5
Протокол: HTTP/1.1

То, что вы видите в этом примере, — зародыш маршрутизации. В настоящем FastAPI всё это разрослось в умный сопоставитель путей, конвертер типов и генератор документации, но принцип не меняется с 1991 года.

Почему FastAPI: четыре причины выбрать его для первого API

На Python есть минимум три популярных способа сделать API: Django REST Framework, Flask и FastAPI. Я почти всегда выбираю FastAPI для новых проектов, и вот почему — по нарастающей важности.

  1. Скорость выполнения. FastAPI построен на ASGI-сервере uvicorn и асинхронной модели — в бенчмарках он стабильно быстрее классического Flask, а местами на порядок быстрее Django. Фраза «FastAPI быстрый» — не маркетинг, а буквальное название.
  2. Скорость разработки. Проверка типов через pydantic и автодополнение в IDE ловят ваши ошибки до запуска сервера. Опечатка в имени поля не пролетит молча — она сломается на этапе написания.
  3. Автодокументация. Каждый эндпоинт сам попадает в интерактивную документацию Swagger по адресу /docs. Документация, которая всегда актуальна, — редкость в индустрии, а у вас она будет бесплатно.
  4. Валидация из коробки. Пришедшие данные проверяет pydantic: строку вместо числа, цену со знаком минус, отсутствующее обязательное поле — всё это отсекается до вашего кода с понятной ошибкой 422.

Для сравнения посмотрите на ту же задачу «отдать товар по пути /products/42» во Flask — она пригодится вам, если решите пройти наш самоучитель Flask:

То же самое на Flask — для сравнения
from flask import Flask, jsonify

app = Flask(__name__)

@app.get("/products/42")
def get_product():
    # Flask требует явного jsonify для правильных заголовков
    return jsonify({"id": 42, "name": "Эспрессо", "price": 199.9})
Сервер в браузере не запустить — это пример реального кода Flask с ожидаемым ответом: тот же JSON, что и у FastAPI.

Разница в двух строчках, но она символична: во Flask вы вручную оборачиваете словарь в jsonify, а FastAPI принимает обычный dict и сам сериализует его. Чем сложнее API, тем сильнее этот разрыв в пользу FastAPI — особенно на валидации. А если вы пришли из Django, знайте: DRF — отличный, но тяжёлый инструмент, где чтобы получить JSON, нужно описать сериализаторы, вьюсеты и роутеры. FastAPI сокращает этот путь до декоратора над функцией.

FastAPI — это современный, быстрый (высокопроизводительный) веб-фреймворк для построения API на Python, основанный на стандартных подсказках типов.

— Себастьян Рамирес, автор FastAPI

Нужен ли REST-фундамент, если фреймворк всё сделает сам?

Короткий ответ: да, и вот тривиальный пример, почему. В FastAPI вы пишете @app.get("/products/{id}") — и в документации появляется красивый список. Но когда в продакшене фронтендер спросит: «Почему на PUT /products/42 вы возвращаете 200, а на создание — 200 вместо 201?» — фреймворк за вас не ответит. REST — это профессиональный язык, на котором общаются бэкендеры, фронтендеры и мобильщики. С ним вы понимаете чужие API, читаете документацию мессенджеров и платёжных систем, спорите о дизайне осмысленно.

Дешёвая проверка на понимание REST: спроектируйте API для библиотеки. Ресурсы — книги (/books) и читатели (/readers). Как выглядит «записать книгу номер 7 за читателем номер 3»? Вариант /lendBook?book=7&reader=3 — не REST. REST-подход: создать ресурс «выдача» — POST /loans с телом {"book_id": 7, "reader_id": 3}. Если вы почувствовали разницу — вы уже мыслите как REST-дизайнер.

Что дальше: от теории к первому коду

Подведём баланс того, что вы уже знаете. API — договор между клиентом и сервером. Запрос — это метод, путь, заголовки, тело. Ответ — это статус, заголовки, JSON. Ресурсы — существительные в URL, действия — в HTTP-методах. FastAPI берёт на себя сериализацию, валидацию и документацию.

Во втором уроке соберём первое приложение на FastAPI: включим компьютер в роли сервера, установим FastAPI и uvicorn, напишем файл main.py с первым эндпоинтом @app.get("/"), запустим его командой uvicorn main:app --reload и откроем живую документацию Swagger. Вы увидите свой первый 200 OK — а заодно разберёте типичные ошибки первого запуска. Один нюанс: сервер целиком в браузерной песочнице не поднимается, поэтому HTTP-часть мы показываем с точным ожидаемым выводом — зато модели pydantic, сердце валидации FastAPI, будут запускаться прямо на странице, начиная с урока 4 про pydantic-модели.

Если хочется параллельно освежить синтаксис Python — декораторы, аннотации типов, словари — загляните в базовый курс. А для практиков в данных будет полезно знать, что API часто обслуживают именно модели машинного обучения: например, сервис, обученный в уроках по NumPy, в итоге оборачивается в FastAPI-эндпоинт и начинает отдавать предсказания по HTTP. Этот урок — первая ступень из десяти; весь маршрут целиком — самоучитель FastAPI.

Что выведет код?

Сначала предскажи ответ в голове — это главный навык программиста.

import json

data = {"name": "Латте", "price": 250, "hot": True}
print(json.dumps(data, ensure_ascii=False))
line = "DELETE /orders/17 HTTP/1.1"
method, path_and_query, protocol = line.split(" ")

print(method, len(path_and_query))
Проверь себя
0 / 5

1. Что такое API одним предложением?

2. Каким HTTP-методом в REST правильно удалять товар с id 42?

3. Клиент отправил данные нового товара, но поле «цена» не прошло проверку. Какой статус вернёт FastAPI?

4. Что произойдёт после json.loads('{"temp": 12}')?

5. Почему GET-запрос считается «безопасным» методом?

Карточки терминов
Запомнено: 0 / 6
Практика

Соберите JSON-ответ сервера для товара «Капучино» и прочитайте его обратно, как это делает FastAPI: сериализуйте словарь в строку JSON (с кириллицей в читаемом виде), затем десериализуйте её и выведите цену и тип поля в_stock.

practice.py
Вопросы и ответы по уроку

Что такое API простыми словами?

API — это договор между двумя программами: первая отправляет запрос по правилам (адрес, метод, данные), вторая возвращает предсказуемый ответ. Как меню в ресторане: видно, что можно заказать, и что за это будет.

Чем REST API отличается от обычного сайта?

Сайт отдаёт HTML — разметку для человека и браузера. REST API отдаёт структурированные данные (обычно JSON) для программы: мобильного приложения, фронтенда или другого сервера. Один и тот же бэкенд может обслуживать и то, и другое.

Почему FastAPI называют быстрым?

В двух смыслах: он быстрый по производительности (работает поверх ASGI-сервера uvicorn и поддерживает async/await) и быстрый в разработке (типы, автодокументация Swagger и валидация pydantic экономят часы).

Нужно ли знать базы данных, чтобы начать с FastAPI?

Нет. Первые пять уроков курса обходятся данными в памяти — списками и словарями Python. Настоящая база данных (SQLite через SQLAlchemy) подключается в седьмом уроке, когда CRUD уже освоен.

Чем метод GET отличается от POST в REST?

GET читает данные и тела не имеет — передавать нечего. POST создаёт новый ресурс и несёт его данные в теле запроса, например POST /products с {"name": "Латте", "price": 250}. А действие кодируется методом, а не адресом: DELETE /products/42, а не /deleteProduct42.

Понравился урок? Сошлитесь на него

«Это разделение — причина, по которой API живут десятилетиями, пока приложения вокруг них переписывают по три раза.»

Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.

TelegramVK

Похожие уроки по темам

Подобраны автоматически по пересечению тем и ключевых слов.

Проверьте знания по FastAPI

В челлендже — 20 задач по FastAPI, по 2 из каждого урока этого раздела. Формат: фрагмент кода и четыре варианта — что напечатает. После ответа — вердикт и объяснение со ссылкой на урок-источник.

Тест по FastAPI: 20 задач