JavaRush /Курси /Модуль 4: FastAPI /Приклад CRUD API: створення, читання, оновлення, видаленн...

Приклад CRUD API: створення, читання, оновлення, видалення даних

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

CRUD — це абревіатура, яка розшифровується як Create, Read, Update і Delete, тобто "Створити, Прочитати, Оновити, Видалити". Всі ці операції лежать в основі кожного додатка, який працює з даними. Хочеш записати користувача в базу? Це Create. Потрібно показати список товарів? Read. А якщо користувач вирішив оновити свій номер телефону? Update. Ну а видалення даних (іноді з сумом, як прощання) — це Delete.

На співбесідах на позицію Python-розробника вас обов'язково спитають про реалізацію CRUD API. У реальному житті такі API використовуються для управління об'єктами, взаємодії з базою даних і побудови надійних систем. На практиці API, які ми створюємо, майже завжди складаються з подібних операцій.

Сьогодні ми зробимо міні-додаток на FastAPI, яке буде керувати списком книг. Кожна книга буде характеризуватися такими атрибутами:

  • id — унікальний ідентифікатор книги (ціле число).
  • title — назва книги (рядок).
  • author — автор (рядок).
  • year — рік публікації (ціле число).

Налаштування проєкту

Спершу переконайся, що в тебе встановлені FastAPI, Uvicorn і Pydantic. Якщо ні — виправимо це командою:

pip install fastapi uvicorn pydantic

Створи структуру проєкту:


crud_app/
├── main.py
└── models.py

У файлі main.py буде описана логіка нашого додатка, а models.py — місце, де ми визначимо наші Pydantic-моделі.


Моделювання даних

Почнемо з визначення книги як об'єкта. Відкрий models.py і створи наступне:


from pydantic import BaseModel
from typing import Optional

# Модель даних для книги
class Book(BaseModel):
    id: int
    title: str
    author: str
    year: int

# Модель для оновлення книги (часткове оновлення)
class BookUpdate(BaseModel):
    title: Optional[str] = None
    author: Optional[str] = None
    year: Optional[int] = None

Ми визначили дві моделі:

  • Book — повна модель книги.
  • BookUpdate — дозволяє оновлювати лише частину полів об'єкта.

Реалізація CRUD-операцій

Тепер переходимо до головного файлу main.py. Почнемо з підключення базових бібліотек і ініціалізації FastAPI:


from fastapi import FastAPI, HTTPException
from models import Book, BookUpdate

app = FastAPI()

# Сховище даних
books = []  # В цій реалізації використовуємо список для зберігання книг.

Створення книги (Create)

Ми створимо endpoint, який приймає дані книги в форматі JSON, валідирує їх і додає книгу до списку.


@app.post("/books/", response_model=Book)
async def create_book(book: Book):
    # Перевіряємо, чи вже є книга з таким id
    for existing_book in books:
        if existing_book.id == book.id:
            raise HTTPException(status_code=400, detail="Книга з таким ID вже існує")
    
    books.append(book)
    return book

Отримання списку книг (Read)

Тепер зробимо endpoint для читання списку всіх книг.


@app.get("/books/", response_model=list[Book])
async def get_books():
    return books

Або окремої книги за id:


@app.get("/books/{book_id}", response_model=Book)
async def get_book(book_id: int):
    for book in books:
        if book.id == book_id:
            return book
    raise HTTPException(status_code=404, detail="Книга не знайдена")

Оновлення книги (Update)

Оновлення книги буде оброблятися через PUT-запит, а часткове оновлення реалізоване з використанням моделі BookUpdate.


@app.put("/books/{book_id}", response_model=Book)
async def update_book(book_id: int, book_update: BookUpdate):
    for book in books:
        if book.id == book_id:
            # Оновлюємо тільки ті поля, які були передані
            if book_update.title is not None:
                book.title = book_update.title
            if book_update.author is not None:
                book.author = book_update.author
            if book_update.year is not None:
                book.year = book_update.year
            return book
    
    raise HTTPException(status_code=404, detail="Книга не знайдена")

Видалення книги (Delete)

Для видалення книги також додамо endpoint:


@app.delete("/books/{book_id}", response_model=dict)
async def delete_book(book_id: int):
    for book in books:
        if book.id == book_id:
            books.remove(book)
            return {"message": "Книга успішно видалена"}
    
    raise HTTPException(status_code=404, detail="Книга не знайдена")

Валідація даних і обробка помилок

FastAPI вже автоматично робить багато роботи за нас завдяки Pydantic. Якщо дані не відповідатимуть моделі, API поверне зрозуміле повідомлення про помилку. Приклад:


{
  "detail": [
    {
      "loc": ["body", "title"],
      "msg": "field required",
      "type": "value_error.missing"
    }
  ]
}

У випадку користувацьких помилок, таких як спроба створити книгу з уже існуючим ID, використовуємо HTTPException.


Швидка інтеграція з базою даних (опційно)

Наразі наші дані зберігаються в пам'яті (список books). Це зручно для швидких експериментів, але непридатне для реальних проєктів. Підключимо базу даних SQLite.

Встанови SQLAlchemy і aiosqlite:

pip install sqlalchemy aiosqlite

Винесемо моделі в models.py і створимо SQLAlchemy ORM:


from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

Base = declarative_base()

# Модель книги для роботи з базою даних
class BookDB(Base):
    __tablename__ = "books"
    id = Column(Integer, primary_key=True, index=True)
    title = Column(String, index=True)
    author = Column(String)
    year = Column(Integer)

# Створюємо SQLite базу даних
DATABASE_URL = "sqlite:///./books.db"
engine = create_engine(DATABASE_URL)
Base.metadata.create_all(bind=engine)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Тепер в CRUD-endpoint'ах ти будеш використовувати SessionLocal для взаємодії з базою. Наприклад, замість додавання в список books використовуй базовий SQL-запит:


db = SessionLocal()
db.add(new_book)
db.commit()

Цей крок виводить твою реалізацію на новий рівень, дозволяючи працювати з великими обсягами даних.


Ось і все! Ми створили повноцінний CRUD API, який можна далі покращувати і адаптувати під потреби твого проєкту. Це потужний старт для побудови твоїх додатків!

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ