Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions crud.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from fastapi import Query
from sqlalchemy import select
from sqlalchemy.orm import Session

import models
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The database uses an in-memory SQLite URL (sqlite:///:memory:). For a library management system where data persistence matters, consider using a file-based database like sqlite:///./library.db so data persists across restarts.

from schemas import AuthorCreate, BookCreate


def get_all_authors(
db: Session,
skip: int = Query(default=0, ge=0),
limit: int = Query(default=9, ge=1)
):

return db.scalars(select(models.Author)).offset(skip).limit(limit).all()


def get_author(
db: Session,
author_id: int
):
return db.scalar(select(models.Author).where(models.Author.id == author_id))


def create_author(db: Session, author: AuthorCreate):
db_author = models.Author(
name=author.name,
bio=author.bio,
)
db.add(db_author)
db.commit()
db.refresh(db_author)

return db_author


def get_all_books(db: Session,
author_id: int | None = None,
skip: int = Query(default=0, ge=0),
limit: int = Query(default=9, ge=1)
):
queryset = select(models.Book)

if author_id is not None:
queryset = queryset.join(models.Author).where(models.Author.id == author_id)

Comment on lines +22 to +46
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing /books/ POST endpoint to create a new book for a specific author, which is required by the task checklist item #8.

Comment on lines +22 to +46
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing /books/ GET endpoint to retrieve a list of books with pagination (skip, limit), which is required by the task checklist item #8.

Comment on lines +22 to +46
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing /books/?author_id={id} filtering capability via query parameter for books by author ID, which is required by the task checklist item #8.

return db.scalars(queryset).offset(skip).limit(limit).all()


def get_book(db: Session, book_id: int):
return db.scalar(select(models.Book).where(models.Book.id == book_id))


def create_book(db: Session, book: BookCreate):
db_book = models.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
16 changes: 16 additions & 0 deletions database.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker


SQLALCHEMY_DATABASE_URL = "sqlite:///./library.db"

engine = create_engine(
SQLALCHEMY_DATABASE_URL, echo=True,
)

SessionLocal = sessionmaker(autocommit=True,
autoflush=False,
bind=engine)

base = declarative_base()
Binary file added library.db
Binary file not shown.
69 changes: 69 additions & 0 deletions main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
from sqlalchemy.orm import Session

from fastapi import FastAPI, Depends, HTTPException

import crud
import schemas
from database import base, engine, SessionLocal

app = FastAPI()


base.metadata.create_all(bind=engine)


def get_db() -> Session:
db = SessionLocal()
try:
yield db
finally:
db.close()


@app.get("/authors/", response_model=list[schemas.AuthorList])
def authors_list(db: Session = Depends(get_db)):
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This endpoint is missing skip and limit query parameters. The task requirement states 'Retrieve a list of authors with pagination (skip, limit)' - add skip: int = Query(default=0, ge=0) and limit: int = Query(default=9, ge=1) parameters and pass them to crud.get_all_authors().

return crud.get_all_authors(db)


@app.get("/authors/{author_id}/", response_model=schemas.AuthorList)
def author_detail(
author_id: int,
db: Session = Depends(get_db)
):
author = crud.get_author(db=db, author_id=author_id)

if author is None:
raise HTTPException(status_code=404, detail="Author with this id is not found")

return author


@app.post("/authors/", response_model=schemas.AuthorList)
def author_create(
author: schemas.AuthorCreate,
db: Session = Depends(get_db)
):
return crud.create_author(db=db, author=author)
Comment on lines +1 to +50
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing endpoints: The task requires implementing: (1) Create a new book for a specific author, (2) Retrieve a list of books with pagination, and (3) Filter books by author ID. These endpoints are not present in main.py despite CRUD functions (create_book, get_all_books) and schemas (BookCreate, BookList) being properly implemented.



@app.get("/books/", response_model=list[schemas.BookList])
def get_all_books(
author_id: int | None = None,
db: Session = Depends(get_db)
):
Comment on lines +52 to +59
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This endpoint is missing skip and limit query parameters. The task requirement states 'Retrieve a list of books with pagination (skip, limit)' - add skip: int = Query(default=0, ge=0) and limit: int = Query(default=9, ge=1) parameters and pass them to crud.get_all_books().

return crud.get_all_books(db=db, author_id=author_id)


@app.get("/books/{book_id}/", response_model=schemas.BookList)
def book_detail(book_id: int, db: Session = Depends(get_db)):
book = crud.get_book(db=db, book_id=book_id)

if book is None:
raise HTTPException(status_code=404, detail="Book with this id is not found")

return book


@app.post("/books/", response_model=schemas.BookList)
def create_book(book: schemas.BookCreate, db: Session = Depends(get_db)):
return crud.create_book(db=db, book=book)
29 changes: 29 additions & 0 deletions models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from datetime import date

from sqlalchemy import String, ForeignKey, Date

from database import base
from sqlalchemy.orm import Mapped, mapped_column, relationship


class Author(base):
__tablename__ = "author"

id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(255), unique=True)
bio: Mapped[str] = mapped_column(String(511))

books: Mapped[list["Book"]] = relationship(back_populates="author")


class Book(base):
__tablename__ = "book"

id: Mapped[int] = mapped_column(primary_key=True)
title: Mapped[str] = mapped_column(String(255))
summary: Mapped[str] = mapped_column(String(255))
publication_date: Mapped[date] = mapped_column(Date)
author_id: Mapped[int] = mapped_column(ForeignKey("author.id"))

author: Mapped["Author"] = relationship(back_populates="books")

35 changes: 35 additions & 0 deletions schemas.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from pydantic import BaseModel, ConfigDict

from datetime import date


class AuthorBase(BaseModel):
name: str
bio: str


class AuthorCreate(AuthorBase):
pass


class AuthorList(AuthorBase):
id: int

model_config = ConfigDict(from_attributes=True)


class BookBase(BaseModel):
title: str
summary: str
publication_date: date


class BookCreate(BookBase):
author_id: int


class BookList(BookBase):
id: int
author: AuthorList

model_config = ConfigDict(from_attributes=True)