Skip to content

Глава 6.1: Соединение FastAPI с фронтендом

Время изучения: 30 минут


1. Возвращение к "гипердвигателю": Сравнение протоколов

В прошлой главе мы состыковали наш ЦУП (фронтенд) с "МКС" (Laravel API). Теперь мы вернемся к нашему сверхсветовому истребителю (FastAPI) и проведем ту же операцию.

Цель этой главы — не просто повторить действия, а сравнить два подхода. Это как если бы один и тот же корабль Dragon сначала стыковался с МКС, а потом с китайской станцией "Тяньгун". Стыковочный узел тот же (REST), но могут быть нюансы в процедурах и расположении портов.

💡 Космическая аналогия:

Процесс одинаков: подлететь, выровняться, состыковаться. Но для "МКС" нужно было использовать порт /api/planets, а для "Тяньгун" — порт /spaceships. Наш оператор в ЦУПе должен знать эти детали, чтобы миссия прошла успешно.


2. Подготовка "истребителя" (FastAPI) к стыковке

Мы уже делали это в Главе 4.2, но давайте убедимся, что все на месте.

Шаг 1: Запускаем сервер FastAPI

  1. Остановите сервер Laravel, если он запущен (чтобы не было конфликта портов).
  2. Откройте терминал в папке вашего FastAPI-проекта.
  3. Активируйте виртуальное окружение:

    • Windows: .\venv\Scripts\Activate.ps1
    • macOS / Linux: source venv/bin/activate
  4. Запустите сервер:

    uvicorn main:app --reload
    
    Сервер будет доступен по адресу http://127.0.0.1:8000.

Шаг 2: Проверяем настройки CORS в main.py

Убедитесь, что в вашем FastAPI-проекте есть настроенный CORSMiddleware, который мы добавили ранее. Он должен разрешать запросы с адреса вашего фронтенда.

# main.py
from fastapi.middleware.cors import CORSMiddleware

# ...

origins = [
    "http://127.0.0.1:5500", # Адрес Live Server
    "null", # Для file:///
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# ...
Если все на месте, ваш FastAPI-сервер полностью готов.


3. Перенастройка "антенны" ЦУПа обратно на FastAPI

Теперь самое интересное — минимальные изменения, которые нужно внести в наш JavaScript, чтобы он снова работал с FastAPI.

Шаг 1: Меняем базовый URL

Откройте api.js и верните API_BASE_URL к его первоначальному значению.

// api.js

// Указываем URL нашего FastAPI API
const API_BASE_URL = 'http://127.0.0.1:8000'; // <-- Без /api!

// ... остальной код apiRequest ...

Шаг 2: Адаптация к структуре ответа FastAPI

Вспомним, что наш GET /spaceships в FastAPI возвращает простой массив, а не объект с пагинацией. Это значит, что нам нужно вернуть код fetchAndDisplayFleet к его первоначальному виду.

Измените функцию fetchAndDisplayFleet в app.js:

// app.js

async function fetchAndDisplayFleet() {
    try {
        fleetListContainer.innerHTML = '<p>Загрузка телеметрии от FastAPI...</p>';
        const ships = await apiRequest('/spaceships'); // <-- Запрос на /spaceships

        // В FastAPI у нас простой массив, поэтому ключ .data не нужен!

        fleetListContainer.innerHTML = '';
        if (ships.length === 0) {
            fleetListContainer.innerHTML = '<p>В реестре нет аппаратов.</p>';
            return;
        }

        ships.forEach(ship => {
            // Возвращаем нашу оригинальную функцию для создания карточек
            const card = createShipCard(ship);
            fleetListContainer.appendChild(card);
        });
    } catch (error) {
        fleetListContainer.innerHTML = `<p style="color: #ff6b6b;">Ошибка загрузки флота: ${error.message}</p>`;
    }
}

// Оригинальная функция для создания карточек кораблей
function createShipCard(ship) {
    const card = document.createElement('div');
    card.className = 'card';
    card.innerHTML = `
        <h3>${ship.name} (ID: ${ship.id})</h3>
        <p>Тип: ${ship.type}</p>
        <p>Год запуска: ${ship.launch_year}</p>
        <p>Статус: ${ship.status}</p>
        <div class="card-actions">
            <button class="edit-btn" data-ship-id="${ship.id}">Изменить</button>
            <button class="delete-btn" data-ship-id="${ship.id}">Списать</button>
        </div>
    `;
    return card;
}

Шаг 3: Проверка CRUD-операций

Поскольку наши Pydantic-модели в FastAPI и поля в HTML-форме совпадают (name, type, launch_year, status), функции handleSaveShip и handleDeleteShip должны заработать без изменений, так как они уже нацелены на эндпоинт /spaceships.


4. Итоги сравнения: Что это значит для фронтенд-разработчика?

  • Универсальность REST: Вы наглядно убедились, что для фронтенда не имеет значения, на чем написан бэкенд (PHP/Laravel или Python/FastAPI), если он следует принципам REST.
  • Важность документации: Основные отличия заключались в URL эндпоинтов и структуре JSON-ответов. Это именно то, что должно быть описано в документации API. Без нее фронтенд-разработчик будет работать "вслепую".
  • Гибкость фронтенда: Ваш JavaScript-код должен быть достаточно гибким, чтобы легко адаптироваться к разным форматам данных (например, проверять, есть ли ключ data, или это просто массив).

Вывод: Навык работы с REST API — это универсальный ключ, который открывает двери к взаимодействию с любым современным бэкендом.


Квиз для закрепления

1. Основное отличие в URL между нашим Laravel API и FastAPI API было в...

2. Какое главное изменение в коде JS потребовалось при переключении с пагинированного ответа Laravel на простой массив FastAPI?

3. Этот эксперимент доказывает, что для фронтенд-разработчика...

4. Настройка CORS является задачей...

5. Если бы в FastAPI использовалась пагинация, как в Laravel, что бы нам пришлось сделать на фронтенде?


🚀 Итог главы:

Вы успешно переключили "протоколы связи" вашего ЦУПа и на практике сравнили работу с двумя разными бэкенд-системами.

  • ✅ Вы закрепили навык настройки API_BASE_URL для переключения между серверами.
  • ✅ Вы поняли, как важна структура ответа (data vs простой массив) и как адаптировать к ней фронтенд.
  • ✅ Вы осознали, что хороший фронтенд-разработчик должен быть готов к работе с любым RESTful API, внимательно изучив его документацию.

Навык универсальной стыковки получен! Теперь, когда мы умеем настраивать базовую связь, пора поговорить о более сложных протоколах — CORS, аутентификации и безопасности.

📌 Проверка:

  • Убедитесь, что ваш FastAPI-сервер запущен.
  • Убедитесь, что вы вернули API_BASE_URL и логику обработки ответа в app.js к варианту для FastAPI.
  • Проверьте, что ваш фронтенд снова корректно выполняет все CRUD-операции с FastAPI-бэкендом.

⚠️ Если ошибки:

  • CORS error: Убедитесь, что FastAPI-сервер запущен с правильными настройками CORS.
  • Ошибка Cannot read properties of undefined (reading 'length'): Возможно, вы забыли убрать обращение к .data из responseData.
  • 404 Not Found: Проверьте API_BASE_URL — у FastAPI нет префикса /api.