JavaRush /Курси /Модуль 4: FastAPI /Видалення даних через DELETE-запити

Видалення даних через DELETE-запити

Модуль 4: FastAPI
Рівень 2 , Лекція 4
Відкрита

Привіт! Готові зануритися в світ API-запитів і навчитися майстерно видаляти дані? Сьогодні у нас у плані DELETE-запити — одна з крапок опори REST API. Поговоримо про те, як реалізувати видалення ресурсів через FastAPI, як це пов’язано з іншими HTTP-методами і, звісно, торкнемося асинхронності. Поїхали!

Основи DELETE-запитів

DELETE-запити є частиною CRUD (Create, Read, Update, Delete) операцій. Вони використовуються для видалення ресурсу на сервері. Робота з DELETE-запитами має кілька ключових особливостей:

  1. Йдемо прямо: DELETE-запити прямо вказують, що конкретний ресурс має бути видалений. Зазвичай ідентифікатор ресурсу передається через параметри шляху.
  2. Безповоротно: після успішного виконання DELETE-запиту ресурс має вважатися видаленим. REST API припускає, що операція DELETE ідемпотентна, тобто повторний запит має давати той самий результат (ресурс вже видалено).
  3. Авторизація та безпека: видалення — ризикована операція, тому варто особливо уважно перевіряти права користувача.

Створення асинхронного endpoint-а для видалення даних

Крок 1: Налаштовуємо DELETE-endpoint

FastAPI дозволяє легко створювати endpoint-и для всіх 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} успішно видалено"}
  1. Маршрут @app.delete: Ми використовуємо метод @app.delete, щоб вказати, що це endpoint для DELETE-запитів.
  2. Параметри шляху: Ми приймаємо resource_id з URL, щоб зрозуміти, який ресурс видаляти.
  3. Перевірка існування: Якщо ресурс з даним ID не знайдено, ми повертаємо помилку 404.
  4. Видалення і відповідь: Якщо ресурс знайдено, він видаляється зі словника, а клієнт отримує підтвердження.

Спробуйте надіслати DELETE-запит (curl або Postman) на endpoint /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} успішно видалено"}

Що додали?

  1. Типізація і опис параметра: використовуємо Path, щоб додати валідацію і документацію.
  2. Перевірка 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 став ще більш повним і корисним!

3
Опитування
Асинхронні ендпоінти FastAPI, рівень 2, лекція 4
Недоступний
Асинхронні ендпоінти FastAPI
Асинхронні ендпоінти FastAPI
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ