From 3ccaf50a30cca7380bccbbf9228aec258ba00956 Mon Sep 17 00:00:00 2001 From: JustVov4uk Date: Sat, 16 May 2026 17:47:39 +0200 Subject: [PATCH 1/2] Solution --- .gitignore | 4 ++++ crud.py | 41 +++++++++++++++++++++++++++++++++++++++++ database.py | 14 ++++++++++++++ main.py | 39 +++++++++++++++++++++++++++++++++++++++ models.py | 25 +++++++++++++++++++++++++ requirements.txt | 16 ++++++++++++++++ schemas.py | 36 ++++++++++++++++++++++++++++++++++++ 7 files changed, 175 insertions(+) create mode 100644 crud.py create mode 100644 database.py create mode 100644 main.py create mode 100644 models.py create mode 100644 requirements.txt create mode 100644 schemas.py diff --git a/.gitignore b/.gitignore index 7ed07d08..6fd6931b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,10 @@ __pycache__/ *.py[cod] *$py.class +database.db +database.py +.idea + # C extensions *.so diff --git a/crud.py b/crud.py new file mode 100644 index 00000000..59ef7c40 --- /dev/null +++ b/crud.py @@ -0,0 +1,41 @@ +from sqlalchemy import select +from models import Author, Book +from schemas import AuthorCreate, BookCreate + + +def get_author(db, author_id: int): + result = db.execute(select(Author).where(Author.id == author_id)) + author = result.scalars().first() + return author + +def get_authors(db, skip: int = 0, limit: int = 10): + result = db.execute(select(Author).offset(skip).limit(limit)) + authors = result.scalars().all() + return authors + +def create_author(db, author: AuthorCreate): + db_author = Author(name=author.name, bio=author.bio) + db.add(db_author) + db.commit() + db.refresh(db_author) + return db_author + +def get_books(db, skip: int = 0, limit: int = 10, author_id: int = None): + query = select(Book) + if author_id: + query = query.where(Book.author_id == author_id) + result = db.execute(query.offset(skip).limit(limit)) + books = result.scalars().all() + return books + +def create_book(db, book: BookCreate): + db_book = Book( + title=book.title, + summary=book.summary, + publication_date=book.publication_date, + author_id=book.author_id + ) + db.add(db_book) + db.commit() + db.refresh(db_book) + return db_book diff --git a/database.py b/database.py new file mode 100644 index 00000000..6ed72fc7 --- /dev/null +++ b/database.py @@ -0,0 +1,14 @@ +from sqlalchemy import create_engine +from sqlalchemy.orm import DeclarativeBase, sessionmaker + +SQLALCHEMY_DATABASE_URL = "sqlite:///database.db" + +engine = create_engine( + SQLALCHEMY_DATABASE_URL, + connect_args={"check_same_thread": False}, +) +SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) + + +class Base(DeclarativeBase): + pass diff --git a/main.py b/main.py new file mode 100644 index 00000000..cf263873 --- /dev/null +++ b/main.py @@ -0,0 +1,39 @@ +from typing import List +from fastapi import FastAPI, Depends +from sqlalchemy.orm import Session +import crud +from database import SessionLocal +from schemas import AuthorRead, AuthorCreate, BookCreate, BookRead + +app = FastAPI() + +def get_db(): + db = SessionLocal() + try: + yield db + finally: + db.close() + +@app.get("/") +def root() -> dict: + return {"message": "Hello World"} + +@app.post("/authors/", response_model=AuthorRead) +def create_author(author: AuthorCreate, db: Session = Depends(get_db)): + return crud.create_author(db=db, author=author) + +@app.get("/authors/", response_model=List[AuthorRead]) +def read_authors(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)): + return crud.get_authors(db, skip=skip, limit=limit) + +@app.get("/authors/{author_id}", response_model=AuthorRead) +def read_author(author_id: int, db: Session = Depends(get_db)): + return crud.get_author(db, author_id=author_id) + +@app.post("/books/", response_model=BookRead) +def create_book(book: BookCreate, db: Session = Depends(get_db)): + return crud.create_book(db, book=book) + +@app.get("/books/", response_model=List[BookRead]) +def read_books(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)): + return crud.get_books(db, skip=skip, limit=limit) diff --git a/models.py b/models.py new file mode 100644 index 00000000..2752a320 --- /dev/null +++ b/models.py @@ -0,0 +1,25 @@ +import datetime +from typing import List +from sqlalchemy import ForeignKey +from sqlalchemy.orm import Mapped, mapped_column, relationship +from database import Base + + +class Author(Base): + __tablename__ = "authors" + + id: Mapped[int] = mapped_column(primary_key=True) + name: Mapped[str] = mapped_column(unique=True) + bio: Mapped[str] = mapped_column() + books: Mapped[List["Book"]] = relationship(back_populates="author") + + +class Book(Base): + __tablename__ = "books" + + id: Mapped[int] = mapped_column(primary_key=True) + title: Mapped[str] = mapped_column() + summary: Mapped[str] = mapped_column() + publication_date: Mapped[datetime.date] = mapped_column() + author_id: Mapped[int] = mapped_column(ForeignKey("authors.id")) + author: Mapped[Author] = relationship(back_populates="books") diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 00000000..3797c229 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,16 @@ +annotated-doc==0.0.4 +annotated-types==0.7.0 +anyio==4.13.0 +click==8.3.3 +colorama==0.4.6 +fastapi==0.136.1 +greenlet==3.5.0 +h11==0.16.0 +idna==3.15 +pydantic==2.13.4 +pydantic_core==2.46.4 +SQLAlchemy==2.0.49 +starlette==1.0.0 +typing-inspection==0.4.2 +typing_extensions==4.15.0 +uvicorn==0.47.0 diff --git a/schemas.py b/schemas.py new file mode 100644 index 00000000..3af6ab61 --- /dev/null +++ b/schemas.py @@ -0,0 +1,36 @@ +import datetime +from typing import List +from pydantic import BaseModel + + +class AuthorCreate(BaseModel): + name: str + bio: str + + +class BookRead(BaseModel): + id: int + title: str + summary: str + publication_date: datetime.date + author_id: int + + class Config: + from_attributes = True + + +class AuthorRead(BaseModel): + id: int + name: str + bio: str + books: List[BookRead] + + class Config: + from_attributes = True + + +class BookCreate(BaseModel): + title: str + summary: str + publication_date: datetime.date + author_id: int From 9214f87b4997b2f14fb7239862725d4d304b6c9b Mon Sep 17 00:00:00 2001 From: JustVov4uk Date: Sat, 16 May 2026 17:59:38 +0200 Subject: [PATCH 2/2] Solution --- main.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/main.py b/main.py index cf263873..df28a760 100644 --- a/main.py +++ b/main.py @@ -2,9 +2,11 @@ from fastapi import FastAPI, Depends from sqlalchemy.orm import Session import crud -from database import SessionLocal +from database import SessionLocal, Base, engine from schemas import AuthorRead, AuthorCreate, BookCreate, BookRead +Base.metadata.create_all(bind=engine) + app = FastAPI() def get_db(): @@ -35,5 +37,10 @@ def create_book(book: BookCreate, db: Session = Depends(get_db)): return crud.create_book(db, book=book) @app.get("/books/", response_model=List[BookRead]) -def read_books(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)): - return crud.get_books(db, skip=skip, limit=limit) +def read_books( + skip: int = 0, + limit: int = 10, + db: Session = Depends(get_db), + author_id: int = None, +): + return crud.get_books(db, skip=skip, limit=limit, author_id=author_id)