Задача курса
FastAPI и база данных: обновление и удаление записи
Курс «FastAPI для начинающих: API с базой данных и тестами» · урок «Обновление и удаление в базе»
Условие
Сохранённые изменения карточки
В Roomly каждая переговорная существует как отдельная карточка с собственными сведениями: как минимум названием и вместимостью. Офис-менеджер обращается к этим карточкам, когда в офисе что-то меняется — комнату переименовывают после ремонта или пересматривают, сколько человек в ней умещается. Важно, что речь идёт именно об исправлении уже известной комнаты, а не о создании новой: карточка сохраняет свою идентичность, меняются лишь конкретные сведения.
Исправление применяется избирательно: если офис-менеджер указал только одно поле, именно оно и обновляется, тогда как остальные данные комнаты остаются нетронутыми. При этом система не допускает частичного или скрытого применения изменений — если переданные сведения по какой-либо причине неприемлемы, карточка остаётся в прежнем виде целиком, без каких-либо промежуточных следов.
Система должна уверенно справляться и с граничными ситуациями. Если офис-менеджер попытается исправить комнату, которой нет в базе, он получит явный сигнал об отсутствии — никакой новой записи при этом не возникает. После успешного исправления повторное обращение к карточке должно возвращать именно обновлённые данные, а не прежние: это единственный способ убедиться, что изменение действительно сохранилось.
Что уже дано
Это самостоятельная SQLAlchemy-лаба с id/name/capacity. Полный видимый файл уже содержит модели, схемы, настройки базы, get_db и работающие GET/POST/PUT/DELETE. Новый TODO только в PATCH: остальные обработчики переписывать не нужно. Это ограниченная часть полного checkpoint, где остаётся весь CRUD; прошлые поля большого проекта эта сокращённая лаба не мигрирует.
Перед видимым файлом служебная подготовка создаёт пустой временный каталог внутри рабочей папки и задаёт DATABASE_URL: str — SQLite URL собственного файла roomly.db. Используйте именно это имя; создавать путь или открывать прежние базы не нужно. Публичный переходник выполняет HTTP через TestClient, передаёт диагностические наблюдения и читает этот же файл отдельным SQLite-соединением. Данные для проверок поступают через RPC, ожидаемые ответы в переходнике отсутствуют. После проверки он закрывает свои ресурсы и удаляет только собственный временный каталог. Писать переходник, SQL-диагностику, управление файлами или тесты не требуется. Готовый наблюдатель также сообщает присваивания ORM-атрибутам и выполненные SQL-изменения, не выполняя их вместо решения. Он позволяет отличить отказ до изменения от последующего отката уже сделанного изменения.
Что нужно сделать
Реализуйте PATCH /api/rooms/{room_id} через предоставленную Session. Для найденной Room меняются только явно переданные name/capacity; id и остальные комнаты сохраняются. Успех —200 с ровно id/name/capacity; {} оставляет карточку прежней. Повтор одинакового допустимого изменения успешен. Изменения должны быть зафиксированы: отдельные GET и чтение того же файла после завершения запроса видят новое состояние.
Явный null любого из двух полей у существующей Room отклоняется422/{"detail":"Fields cannot be null"} до первого присваивания атрибута или SQL-изменения. Сначала проверьте допустимость всего исправления; способ реализации выбираете вы. Для отсутствующей комнаты с допустимым телом верните404/{"detail":"Room not found"}, без создания строки. Типизированный path и готовая RoomPatch сохраняют стандартный422 для неверных ненулевых значений: name длиной2–50 и capacity:int1–50. Невалидные и отсутствующие тела не меняют базу. Дополнительные поля, включая id, не меняют идентификатор.
Сохраните уже работающие GET/POST/PUT/DELETE и их публичные ответы. Бронирований, новых полей и новых правил удаления в этой задаче нет.
Ввод и вывод
stdin не используется. Печатать через print в stdout ничего не нужно. После выполнения файла проверяющая система обращается к верхнеуровневому app: публичный переходник вызывает TestClient внутри процесса приложения и передаёт результат скрытой проверке. Запускать Uvicorn, сеть, клиентский скрипт или pytest не требуется.
Для карточки {"id":9,"name":"Кедр","capacity":6} PATCH с {"capacity":8} возвращает ту же карточку с capacity8; следующий GET видит8. PATCH с {"name":"Новое","capacity":null} отклоняется целиком и оставляет оба старых значения.
