Как обработать ситуацию отсутствия данных, если заказ не найден
Что проверяют
Различаете ли вы «данных нет» как нормальный исход и как ошибку, и понимаете ли, на каком слое приложения это решается. Следом обычно спрашивают, какой HTTP-код вернуть и что делать, если заказ существует, но принадлежит другому пользователю.
Как отвечать
Проведите «нет данных» через слои:
- доступ к данным: отсутствие строки не исключение. В SQLAlchemy
session.get(Order, order_id)иscalar_one_or_none()вернутNone, аscalar_one()броситNoResultFound, его берут, только если строка обязана быть. В Djangofilter(pk=pk).first()противget(), который бросаетOrder.DoesNotExist. Сигнатура-> Order | Noneзаставит mypy требовать проверку у вызывающего; - бизнес-логика: сервис решает, что отсутствие значит для сценария, и бросает доменное
OrderNotFound(order_id), которое ничего не знает про HTTP; - API: один обработчик переводит доменные исключения в ответы. В FastAPI это
@app.exception_handler(OrderNotFound)с ответом 404 и телом вроде{"code": "order_not_found"}, в DRF исключениеNotFoundилиget_object_or_404.
Чужой заказ отдают тем же 404: ответ 403 подтверждает, что номер существует, и открывает перебор. Поэтому ищут сразу по паре id и user_id, а не находят заказ и потом сравнивают владельца.
Ещё два момента. «Не найдено» логируют уровнем INFO или WARNING, а не ERROR, иначе боты зальют мониторинг шумом. И если заказ только что создан, а чтение идёт с реплики, «не найден» может означать задержку репликации, такие чтения направляют на мастер.
Где спотыкаются
Возвращают строку с текстом ошибки из функции, которая обычно отдаёт заказ. Вызывающий код получает то объект, то str и падает дальше в неожиданном месте.
Оборачивают запрос в except Exception и превращают любую проблему, включая упавшую базу, в «заказ не найден». Пользователь видит 404, а сбой никто не замечает.
Бросают HTTPException из репозитория или сервиса. Тогда бизнес-логику не переиспользовать в фоновой задаче или CLI, где HTTP нет.