-
Notifications
You must be signed in to change notification settings - Fork 671
Solution #654
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Solution #654
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| from sqlalchemy.orm import Session | ||
| from schemas import AuthorCreate, BookCreate | ||
| import models | ||
|
|
||
|
|
||
| def get_author(db: Session, author_id: int): | ||
| return db.query(models.Author).filter(models.Author.id == author_id).first() | ||
|
|
||
|
|
||
| def get_authors(db: Session, skip: int, limit: int): | ||
| return db.query(models.Author).offset(skip).limit(limit).all() | ||
|
|
||
|
|
||
| def create_author(db: Session, author: AuthorCreate): | ||
| db_author = models.Author(**author.model_dump()) | ||
| db.add(db_author) | ||
| db.commit() | ||
| db.refresh(db_author) | ||
| return db_author | ||
|
|
||
|
|
||
| def get_books(db: Session, skip: int, limit: int, author_id: int = None): | ||
| query = db.query(models.Book) | ||
| if author_id: | ||
| query = query.filter(models.Book.author_id == author_id) | ||
| return query.offset(skip).limit(limit).all() | ||
|
|
||
|
|
||
| def create_book(db: Session, book: BookCreate): | ||
| db_book = models.Book(**book.model_dump()) | ||
| db.add(db_book) | ||
| db.commit() | ||
| db.refresh(db_book) | ||
| return db_book |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| from sqlalchemy import create_engine | ||
| from sqlalchemy.orm import declarative_base | ||
| from sqlalchemy.orm import sessionmaker | ||
|
|
||
| SQLALCHEMY_DATABASE_URL = "sqlite:///./library.db" | ||
|
|
||
| engine = create_engine( | ||
| SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False} | ||
| ) | ||
| SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) | ||
|
|
||
| Base = declarative_base() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| from sqlalchemy.orm import Session | ||
| import crud | ||
| from database import engine, SessionLocal | ||
| from models import Base | ||
| from schemas import AuthorCreate, AuthorResponse, BookResponse, BookCreate | ||
| from fastapi import FastAPI, Depends, HTTPException | ||
| from typing import List | ||
|
|
||
|
|
||
| Base.metadata.create_all(bind=engine) | ||
|
|
||
| app = FastAPI() | ||
|
|
||
| def get_db(): | ||
| db = SessionLocal() | ||
| try: | ||
| yield db | ||
| finally: | ||
| db.close() | ||
|
|
||
| @app.post("/authors", response_model=AuthorResponse) | ||
| def create_author(author: AuthorCreate, db: Session = Depends(get_db)): | ||
| return crud.create_author(db=db, author=author) | ||
|
|
||
|
|
||
| @app.get("/authors", response_model=List[AuthorResponse]) | ||
| def read_authors(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)): | ||
| return crud.get_authors(db, skip=skip, limit=limit) | ||
|
|
||
|
|
||
| @app.get("/authors/{author_id}", response_model=AuthorResponse) | ||
| def read_author(author_id: int, db: Session = Depends(get_db)): | ||
| author = crud.get_author(db, author_id=author_id) | ||
| if not author: | ||
| raise HTTPException(status_code=404, detail="Author not found") | ||
| return author | ||
|
|
||
| @app.post("/authors/{author_id}/books", response_model=BookResponse) | ||
| def create_book(author_id: int, book: BookCreate, db: Session = Depends(get_db)): | ||
| author = crud.get_author(db, author_id=author_id) | ||
| if not author: | ||
| raise HTTPException(status_code=404, detail="Author not found") | ||
| return crud.create_book(db=db, book=book) | ||
|
|
||
|
|
||
| @app.get("/books", response_model=List[BookResponse]) | ||
| def read_books(skip: int = 0, limit: int = 100, author_id: int = None, db: Session = Depends(get_db)): | ||
| return crud.get_books(db, skip=skip, limit=limit, author_id=author_id) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| from datetime import date | ||
| from sqlalchemy import String, ForeignKey | ||
| from sqlalchemy.orm import Mapped, mapped_column, relationship | ||
| from database import Base | ||
|
|
||
|
|
||
| class Author(Base): | ||
| __tablename__ = "author" | ||
|
|
||
| id: Mapped[int] = mapped_column(primary_key=True, index=True) | ||
| name: Mapped[str] = mapped_column(String(255), nullable=False, unique=True) | ||
| bio: Mapped[str] = mapped_column(String(511), nullable=False) | ||
| books: Mapped[list["Book"]] = relationship(back_populates="author") | ||
|
|
||
|
|
||
| class Book(Base): | ||
| __tablename__ = "book" | ||
|
|
||
| id: Mapped[int] = mapped_column(primary_key=True, index=True) | ||
| title: Mapped[str] = mapped_column(String(255), nullable=False,) | ||
| summary: Mapped[str] | ||
| publication_date: Mapped[date] | ||
| author_id: Mapped[int] = mapped_column(ForeignKey("author.id")) | ||
| author : Mapped["Author"] = relationship(back_populates="books") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| from pydantic import BaseModel, ConfigDict | ||
| from datetime import date | ||
|
|
||
|
|
||
| class AuthorBase(BaseModel): | ||
| name: str | ||
| bio: str | ||
|
|
||
|
|
||
| class AuthorCreate(AuthorBase): | ||
| pass | ||
|
|
||
|
|
||
| class AuthorResponse(AuthorBase): | ||
| id: int | ||
| books: list["BookResponse"] | ||
| model_config = ConfigDict(from_attributes=True) | ||
|
|
||
|
|
||
| class BookBase(BaseModel): | ||
| title: str | ||
| summary: str | ||
| publication_date: date | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The |
||
| author_id: int | ||
|
|
||
|
|
||
| class BookCreate(BookBase): | ||
| pass | ||
|
|
||
|
|
||
| class BookResponse(BookBase): | ||
| id: int | ||
| model_config = ConfigDict(from_attributes=True) | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The BookCreate schema requires author_id, but in the POST /authors/{author_id}/books endpoint, the author_id is taken from the URL path. Users would need to provide author_id in both the path AND the request body, which is redundant. Consider creating a separate schema for book creation that excludes author_id, or accepting it only from the request body.