Skip to content

Глава 3.4: CRUD операции для космических аппаратов

Время изучения: 1 час


1. CRUD: Полный цикл управления космической миссией

До сих пор мы только читали данные (Read). Но настоящий Центр Управления Полетами должен уметь всё:

  • Create (Создать): Запустить новый спутник на орбиту.
  • Read (Прочитать): Запросить статус существующего аппарата.
  • Update (Обновить): Скорректировать орбиту или обновить ПО.
  • Delete (Удалить): Свести с орбиты старый спутник.

Эти четыре операции — CRUD — составляют основу большинства API. В этой главе мы реализуем полный цикл для управления нашим флотом.


2. Create: Запуск нового корабля (POST)

Чтобы создать новый космический аппарат, мы будем использовать метод POST. Данные для нового корабля будут передаваться в теле запроса в формате JSON.

Шаг 1: Создаем новую Pydantic-модель для входящих данных Почему нужна новая модель? Потому что при создании корабля мы не знаем его id — его должен присвоить сервер.

Добавьте эту модель в main.py:

# main.py
from pydantic import BaseModel, Field

class SpaceshipCreate(BaseModel):
    """Модель для создания нового корабля (без ID)."""
    name: str = Field(..., min_length=3, max_length=50)
    type: str
    launch_year: int = Field(..., gt=1950)
    status: str
Эта модель почти идентична Spaceship, но она будет использоваться для валидации входящих данных.

Шаг 2: Реализуем endpoint POST /spaceships

# main.py
import random # Добавьте этот импорт вверху файла

# ... остальной код ...

@app.post("/spaceships", response_model=Spaceship, status_code=201)
def create_spaceship(ship: SpaceshipCreate):
    """
    Добавляет новый космический аппарат в реестр.
    """
    # Генерируем новый уникальный ID для корабля
    new_id = max(db_spaceships.keys() or [0]) + 1

    # Создаем объект корабля, соответствующий полной модели Spaceship
    new_ship = Spaceship(id=new_id, **ship.dict())

    # Сохраняем в нашей "базе данных"
    db_spaceships[new_id] = new_ship.dict()

    return new_ship
Расшифровка:

  • @app.post(...): Используем декоратор для POST-запросов.
  • status_code=201: Указываем, что при успешном создании нужно возвращать статус 201 Created.
  • ship: SpaceshipCreate: Вот она, магия! FastAPI автоматически возьмет тело запроса (JSON), провалидирует его по модели SpaceshipCreate и передаст в функцию как объект ship.
  • new_id = ...: Простая логика для генерации нового ID.
  • **ship.dict(): Мы "распаковываем" данные из принятой модели ship в нашу полную модель.
  • response_model=Spaceship: Ответ будет соответствовать полной модели, включая id.

3. Update: Коррекция курса (PUT)

Для полного обновления существующего ресурса используется метод PUT.

Реализуем endpoint PUT /spaceships/{ship_id}:

# main.py
from fastapi import FastAPI, HTTPException # Обновите импорт

# ... остальной код ...

@app.put("/spaceships/{ship_id}", response_model=Spaceship)
def update_spaceship(ship_id: int, ship_update: SpaceshipCreate):
    """
    Полностью обновляет данные о космическом аппарате.
    """
    if ship_id not in db_spaceships:
        raise HTTPException(status_code=404, detail="Космический аппарат не найден")

    updated_ship = Spaceship(id=ship_id, **ship_update.dict())
    db_spaceships[ship_id] = updated_ship.dict()

    return updated_ship

  • ship_update: SpaceshipCreate: Мы снова используем нашу модель для валидации входящих данных.
  • HTTPException: Если корабль с таким id не найден, мы "выбрасываем" стандартное исключение FastAPI, которое превратится в красивый JSON-ответ с кодом 404.

4. Delete: Сход с орбиты (DELETE)

Для удаления ресурса используется метод DELETE. Обычно такой endpoint не возвращает тело ответа.

Реализуем endpoint DELETE /spaceships/{ship_id}:

# main.py
from fastapi import FastAPI, HTTPException, Response, status # Обновите импорт

# ... остальной код ...

@app.delete("/spaceships/{ship_id}", status_code=status.HTTP_204_NO_CONTENT)
def delete_spaceship(ship_id: int):
    """
    Удаляет космический аппарат из реестра.
    """
    if ship_id not in db_spaceships:
        raise HTTPException(status_code=404, detail="Космический аппарат не найден")

    del db_spaceships[ship_id]

    # Возвращаем пустой ответ со статусом 204
    return Response(status_code=status.HTTP_204_NO_CONTENT)

  • status_code=status.HTTP_204_NO_CONTENT: Мы явно указываем статус 204 No Content.
  • del db_spaceships[ship_id]: Удаляем запись из нашего словаря.
  • return Response(...): Возвращаем пустой ответ, так как клиенту не нужны данные об удаленном объекте.

5. Тестирование полного цикла в /docs

Ваш uvicorn должен был перезагрузиться.

  1. Откройте http://127.0.0.1:8000/docs. Теперь у вас полный набор CRUD-операций!
  2. POST: Раскройте эндпоинт POST /spaceships, нажмите "Try it out", заполните JSON-тело (например, создайте "James Webb Telescope") и нажмите "Execute". Вы должны получить ответ 201 с данными нового телескопа.
  3. GET: Теперь выполните GET /spaceships. В списке должен появиться ваш новый телескоп.
  4. PUT: Используйте ID нового телескопа, чтобы обновить его данные через PUT /spaceships/{ship_id}. Например, измените его статус.
  5. DELETE: Используйте тот же ID, чтобы удалить телескоп через DELETE /spaceships/{ship_id}. Вы должны получить пустой ответ со статусом 204.
  6. Проверка: Снова выполните GET /spaceships, чтобы убедиться, что телескоп удален из списка.

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

1. Какой HTTP-метод используется для создания нового ресурса?

2. Стандартный успешный статус-код для операции `DELETE`:

3. Как FastAPI получает данные из тела POST-запроса?

4. `raise HTTPException(status_code=404)` используется для:

5. Почему для создания ресурса (`POST`) мы создали отдельную модель `SpaceshipCreate`?


🚀 Итог главы:

Вы реализовали полный CRUD-цикл и превратили ваше API из простого "информационного табло" в полноценный Центр Управления Флотом!

  • Create: POST /spaceships для запуска новых аппаратов.
  • Read: GET /spaceships и GET /spaceships/{id} для получения данных.
  • Update: PUT /spaceships/{id} для обновления миссий.
  • Delete: DELETE /spaceships/{id} для списания аппаратов.

Ваш флот под полным контролем! В следующей главе мы увидим, как FastAPI автоматически создал для нас подробную "инструкцию по эксплуатации" — интерактивную документацию Swagger.

📌 Проверка:

  • Все 5 эндпоинтов (GET (2), POST, PUT, DELETE) видны и работают в /docs.
  • Вы можете успешно создать, прочитать, обновить и удалить ресурс.
  • При запросе несуществующего ID возвращается ошибка 404.

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

  • NameError: Проверьте, что вы импортировали HTTPException, Response, status.
  • KeyError: Вероятно, вы пытаетесь получить доступ к ID, который уже удален.
  • Неправильная работа PUT или POST: Убедитесь, что вы используете правильную Pydantic-модель в аргументе функции (SpaceshipCreate).