Skip to content

Library Management API#638

Open
yuriistetsura wants to merge 2 commits into
mate-academy:mainfrom
yuriistetsura:main
Open

Library Management API#638
yuriistetsura wants to merge 2 commits into
mate-academy:mainfrom
yuriistetsura:main

Conversation

@yuriistetsura
Copy link
Copy Markdown

No description provided.

Copy link
Copy Markdown

@mateacademy-ai-mentor mateacademy-ai-mentor left a comment

Choose a reason for hiding this comment

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

Review Summary

I am requesting changes because there are a couple of functional gaps that can cause the API to fail at runtime, even though the overall structure and use of FastAPI + SQLAlchemy is solid.

Critical issues that must be fixed:

  • In main.py (near the top, around the imports and app = FastAPI() definition), the app never creates the database tables from your SQLAlchemy models. Per the requirements, you should import Base and engine from db.database and call Base.metadata.create_all(bind=engine) at startup so the authors and books tables exist before any requests are handled.
  • The create_book endpoint in main.py currently uses response_model=BookCreate, which is the input schema and does not include id or the nested author. The typical expectation (and tests) is that a create endpoint returns the full Book schema, so change this to response_model=Book and ensure you actually return a Book-shaped object (including id and, if intended, the related author).
  • Your book-related endpoints return ORM Book instances that include an author relationship, but the SQLAlchemy session is closed by the dependency before FastAPI serializes the response. Because the queries in crud.get_books (and after db.refresh(db_book) in create-book) do not eagerly load DBBook.author, this can lead to DetachedInstanceError. To fix this, adjust the queries in crud.py to eagerly load the relationship, for example using select(DBBook).options(selectinload(DBBook.author))..., or explicitly access/populate db_book.author while the session is still open before returning.

Minor improvements (optional but recommended):

  • Consider adding 404 handling for "get by id" endpoints so that requesting a missing author or book returns a clear not-found error instead of null.

You have done a good job setting up the database module, models, schemas, and basic CRUD wiring; once you address the table creation, response model, and relationship loading issues, your API will be much more robust and aligned with the task requirements.


✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨

Important

Fix the issues, commit the changes, and then re-request my review using the Re-request review button2 in the Reviewers tab.

Tip

If you have any comments about this review, please leave a message in the Add a comment section below and mention me with the @mateacademy-ai-mentor tag3.
I will read your message during my next review of your pull request. Please do not reply directly to my comments, as that feature is not supported yet.

Caution

Do not close the pull request until the review is complete. Closing it early can lead to unexpected behavior and disrupt the review process.

Footnotes

  1. Rate AI review example

  2. Re-request AI review example

  3. Add AI review comments example

Comment thread main.py Outdated
from sqlalchemy.orm import Session

import crud
from db.database import SessionLocal
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You import only SessionLocal from db.database but the app needs to create tables (see requirement). Import Base and the engine (e.g. from db.database import SessionLocal, engine, Base) so you can call Base.metadata.create_all(bind=engine) at startup.

Comment thread main.py
from db.database import SessionLocal
from schemas import AuthorCreate, Book, BookCreate, Author

app = FastAPI(title="Library Management API")
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 code never creates the database tables using the SQLAlchemy models. Per the task you should call Base.metadata.create_all(bind=engine) (for example after imports / at app startup) so the authors and books tables exist when the API runs.

Comment thread main.py Outdated
return crud.get_author_by_id(db=db, author_id=author_id)


@app.post("/book", response_model=BookCreate)
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 create-book endpoint uses response_model=BookCreate, which is the input schema (no id or nested author). It should return the full Book schema (including id and author) or adjust the returned shape to match BookCreate intentionally.

Comment thread main.py
db: Session = Depends(get_db),
author_id: int = None
):
return crud.get_books(db=db, skip=skip, limit=limit, author_id=author_id)
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 return invokes crud.get_books and will return ORM instances with a nested author in the Book response model. Because the DB session is closed after the dependency returns, accessing lazy relationships during response serialization can raise a DetachedInstanceError. Eager-load the author relationship in the query or serialize while the session is open.

Comment thread main.py
@app.get("/books", response_model=list[Book])
def get_books(
skip: int = 0,
limit: int = 10,
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 books query builds select(DBBook).offset(skip).limit(limit) but does not load the author relationship. To safely serialize nested author after the session closes, add relationship loading, e.g. select(DBBook).options(selectinload(DBBook.author))... or joinedload as appropriate.

Comment thread main.py
@app.get("/author/{author_id}", response_model=Author)
def get_authors_by_id(author_id: int, db: Session = Depends(get_db)):
return crud.get_author_by_id(db=db, author_id=author_id)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

After creating the book you call db.refresh(db_book), which refreshes scalar columns but does not guarantee the author relationship is loaded. If the endpoint must return the nested author, either load the relationship before returning (e.g., db.refresh(db_book); _ = db_book.author) or re-query the book with an eager load while the session is still open.

Copy link
Copy Markdown

@mateacademy-ai-mentor mateacademy-ai-mentor left a comment

Choose a reason for hiding this comment

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

Review Summary

Your solution is approved and it clearly meets the core requirements: the FastAPI app, SQLite database configuration, SQLAlchemy models, CRUD utilities, and author/book endpoints are all implemented and wired together correctly. The database layer (db/database.py) and your Pydantic schemas (schemas.py) are set up properly for ORM integration and cover all required fields, so the API should behave as expected for the main use cases. One improvement to consider is validating that an author_id exists before creating a Book (in the function where you construct and commit DBBook), and returning a 400 or 404 instead of relying on a database integrity error during commit(). Similarly, for your GET-by-id endpoints (e.g., fetching a single author or book), it would be more user-friendly to return an explicit 404 when the record is not found rather than None or an empty payload. As a further enhancement, you might catch IntegrityError when creating authors to handle duplicate names gracefully with a clear 400 response. Overall, the implementation is solid and complete, and these suggestions would mainly improve robustness and client-facing error messages.


✨ Please rate this review in the Platform's notification center1. I will be grateful for your feedback! ✨

Footnotes

  1. Rate AI review example

Comment thread db/models.py

id: Mapped[int] = mapped_column(primary_key=True, index=True)
title: Mapped[str] = mapped_column()
summary: Mapped[str] = mapped_column()
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

When creating a book you currently construct and commit the DBBook directly. Consider verifying that the referenced author exists first (e.g., query for the author and return a clear 400/404 if missing) so the endpoint fails with a helpful error instead of raising a DB integrity error during commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants