Привет! Готовы окунуться в мир API-запросов и научиться мастерски удалять данные? Сегодня у нас на повестке DELETE-запросы — одна из краеугольных частей REST API. Мы будем говорить о том, как реализовать удаление ресурсов через FastAPI, как это связано с другими HTTP-методами и, конечно, затронем асинхронность. Поехали!
Основы DELETE-запросов
DELETE-запросы являются частью CRUD (Create, Read, Update, Delete) операций. Они используются для удаления ресурса с сервера. Работа с DELETE-запросами имеет несколько ключевых особенностей:
- Идём напрямик: DELETE-запросы напрямую указывают, что конкретный ресурс должен быть удален. Обычно идентификатор ресурса передаётся через параметры пути.
- Безвозвратно: после успешного выполнения DELETE-запроса ресурс должен считаться удалённым. REST API предполагает, что операция DELETE идемпотентна, то есть повторный запрос должен давать тот же результат (ресурс уже удалён).
- Авторизация и безопасность: удаление — опасная операция, поэтому нужно быть особенно внимательным при проверке прав пользователя.
Создание асинхронного эндпоинта для удаления данных
Шаг 1: Настраиваем DELETE-эндпоинт
FastAPI позволяет легко создавать эндпоинты для всех HTTP-методов, и DELETE — не исключение. Обычно идентификатор удаляемого ресурса передаётся через Path Parameters.
from fastapi import FastAPI, HTTPException
app = FastAPI()
# Пример данных (обычно данные хранятся в базе данных)
resources = {"1": "Ресурс 1", "2": "Ресурс 2", "3": "Ресурс 3"}
@app.delete("/resources/{resource_id}")
async def delete_resource(resource_id: str):
# Проверяем, существует ли ресурс
if resource_id not in resources:
raise HTTPException(status_code=404, detail="Ресурс не найден")
# Удаляем ресурс
del resources[resource_id]
return {"message": f"Ресурс {resource_id} успешно удалён"}
- Маршрут
@app.delete: Мы используем метод@app.delete, чтобы указать, что это эндпоинт для DELETE-запросов. - Параметры пути: Мы принимаем
resource_idиз URL, чтобы понять, какой ресурс удалять. - Проверка существования: Если ресурс с данным ID не найден, мы возвращаем ошибку 404.
- Удаление и ответ: Если ресурс найден, он удаляется из словаря, а клиент получает подтверждение.
Попробуйте отправить DELETE-запрос (curl или Postman) на эндпоинт /resources/2 и убедитесь, что всё работает!
Шаг 2: Валидация и обработка ошибок
Удаление данных — процесс, который может сопровождаться ошибками. Вот несколько примеров ситуаций, которые нужно учитывать:
- Попытка удалить уже несуществующий ресурс.
- Неправильный формат идентификатора (например, вместо числа пришла строка).
- Ошибки доступа (кто-то хочет удалить чужие данные).
Давайте добавим дополнительную обработку:
from fastapi import Path
@app.delete("/resources/{resource_id}")
async def delete_resource(resource_id: str = Path(..., title="ID ресурса", description="ID ресурса, который нужно удалить")):
if not resource_id.isdigit():
raise HTTPException(status_code=400, detail="ID ресурса должен быть числом")
if resource_id not in resources:
raise HTTPException(status_code=404, detail="Ресурс не найден")
del resources[resource_id]
return {"message": f"Ресурс {resource_id} успешно удалён"}
Что добавили?
- Типизация и описание параметра: используем
Path, чтобы добавить валидацию и документацию. - Проверка ID: проверяем, что
resource_idсостоит из цифр. Если это не так, возвращаем ошибку 400 (Bad Request).
Шаг 3: работа с базой данных
Словарь resources — это хорошо для демонстрации, но в реальных приложениях данные хранятся в базе. Давайте разберём пример с использованием SQLite и асинхронного ORM SQLModel.
from sqlmodel import SQLModel, Field, create_engine, select
from fastapi import Depends
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
# Определяем модель данных
class Resource(SQLModel, table=True):
id: int = Field(default=None, primary_key=True)
name: str
# Настройка асинхронной базы данных
DATABASE_URL = "sqlite+aiosqlite:///./test.db"
engine = create_async_engine(DATABASE_URL, echo=True)
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
async def get_session() -> AsyncSession:
async with async_session() as session:
yield session
# Создаём таблицу
async def init_db():
async with engine.begin() as conn:
await conn.run_sync(SQLModel.metadata.create_all)
@app.on_event("startup")
async def on_startup():
await init_db()
@app.delete("/resources/{resource_id}")
async def delete_resource(resource_id: int, session: AsyncSession = Depends(get_session)):
query = select(Resource).where(Resource.id == resource_id)
result = await session.execute(query)
resource = result.scalar_one_or_none()
if resource is None:
raise HTTPException(status_code=404, detail="Ресурс не найден")
await session.delete(resource)
await session.commit()
return {"message": f"Ресурс {resource_id} успешно удалён"}
Шаг 4: авторизация при удалении
Удаление ресурса — это не функция, доступная каждому. Например, только администратор или создатель ресурса может обладать таким правом. Для этого можно использовать систему аутентификации, основанную на JWT (мы изучим это позже).
Вот как можно добавить базовую проверку авторизации:
from fastapi import Security
async def get_current_user(token: str = Security(...)):
# Заглушка для проверки токена
if token != "supersecrettoken":
raise HTTPException(status_code=403, detail="Нет доступа")
return {"username": "admin"}
@app.delete("/resources/{resource_id}")
async def delete_resource(resource_id: str, user: dict = Depends(get_current_user)):
if resource_id not in resources:
raise HTTPException(status_code=404, detail="Ресурс не найден")
del resources[resource_id]
return {"message": f"Ресурс {resource_id} удалён пользователем {user['username']}"}
Лучшие практики работы с DELETE-запросами
- Подтверждение удаления: если операцию удаление нельзя отменить, подумайте о добавлении этапа подтверждения.
- Идемпотентность: повторный DELETE-запрос не должен приводить к дополнительным ошибкам. Например, при повторной попытке удаления можно просто возвращать сообщение "Ресурс уже удалён".
- Авторизация: уделяйте особое внимание проверкам, чтобы удаление не было доступно для всех подряд.
Пример из реальной жизни
DELETE-запросы активно используются в реальных REST API. Например, при создании административной панели для управления пользователями администратор может удалять аккаунты. Важно предусмотреть валидацию, логику проверки прав доступа и оповещение пользователей об удалении их данных.
Вот и всё на сегодня! Теперь вы знаете, как безопасно и эффективно удалять данные через DELETE-запросы в FastAPI. С этим функционалом ваш CRUD API стал ещё более полным и полезным!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ