Created genre table and added links and endpoints for it.

This commit is contained in:
2025-06-25 14:50:28 +03:00
parent 83dbb1824e
commit 9604771439
9 changed files with 158 additions and 19 deletions

View File

@@ -1,14 +1,17 @@
from .author import Author
from .book import Book
from .genre import Genre
from .links import (
AuthorBookLink, GenreBookLink,
AuthorWithBooks, BookWithAuthors,
GenreWithBooks, BookWithAuthorsAndGenres
GenreWithBooks, BookWithGenres,
BookWithAuthorsAndGenres
)
__all__ = [
'Author', 'Book',
'Author', 'Book', 'Genre',
'AuthorBookLink', 'AuthorWithBooks',
'BookWithAuthors', 'GenreBookLink',
'GenreWithBooks', 'BookWithAuthorsAndGenres'
'GenreWithBooks', 'BookWithGenres',
'BookWithAuthorsAndGenres'
]

View File

@@ -9,6 +9,6 @@ if TYPE_CHECKING:
class Genre(GenreBase, table=True):
id: Optional[int] = Field(default=None, primary_key=True, index=True)
books: List["Book"] = Relationship(
back_populates="authors",
back_populates="genres",
link_model=GenreBookLink
)

View File

@@ -0,0 +1,80 @@
from fastapi import APIRouter, Depends, HTTPException
from sqlmodel import Session, select
from library_service.settings import get_session
from library_service.models.db import Genre, GenreBookLink, Book, GenreWithBooks
from library_service.models.dto import (
GenreCreate, GenreUpdate, GenreRead,
GenreList, BookRead
)
router = APIRouter(prefix="/genres", tags=["genres"])
# Create a genre
@router.post("/", response_model=GenreRead)
def create_genre(genre: GenreCreate, session: Session = Depends(get_session)):
db_genre = Genre(**genre.model_dump())
session.add(db_genre)
session.commit()
session.refresh(db_genre)
return GenreRead(**db_genre.model_dump())
# Read genres
@router.get("/", response_model=GenreList)
def read_genres(session: Session = Depends(get_session)):
genres = session.exec(select(Genre)).all()
return GenreList(
genres=[GenreRead(**genre.model_dump()) for genre in genres],
total=len(genres)
)
# Read a genre with their books
@router.get("/{genre_id}", response_model=GenreWithBooks)
def get_genre(genre_id: int, session: Session = Depends(get_session)):
genre = session.get(Genre, genre_id)
if not genre:
raise HTTPException(status_code=404, detail="Genre not found")
books = session.exec(
select(Book)
.join(GenreBookLink)
.where(GenreBookLink.genre_id == genre_id)
).all()
book_reads = [BookRead(**book.model_dump()) for book in books]
genre_data = genre.model_dump()
genre_data['books'] = book_reads
return GenreWithBooks(**genre_data)
# Update a genre
@router.put("/{genre_id}", response_model=GenreRead)
def update_genre(
genre_id: int,
genre: GenreUpdate,
session: Session = Depends(get_session)
):
db_genre = session.get(Genre, genre_id)
if not db_genre:
raise HTTPException(status_code=404, detail="Genre not found")
update_data = genre.model_dump(exclude_unset=True)
for field, value in update_data.items():
setattr(db_genre, field, value)
session.commit()
session.refresh(db_genre)
return GenreRead(**db_genre.model_dump())
# Delete a genre
@router.delete("/{genre_id}", response_model=GenreRead)
def delete_genre(genre_id: int, session: Session = Depends(get_session)):
genre = session.get(Genre, genre_id)
if not genre:
raise HTTPException(status_code=404, detail="Genre not found")
genre_read = GenreRead(**genre.model_dump())
session.delete(genre)
session.commit()
return genre_read

View File

@@ -3,13 +3,13 @@ from sqlmodel import Session, select
from typing import List, Dict
from library_service.settings import get_session
from library_service.models.db import Book, Author, AuthorBookLink
from library_service.models.dto import AuthorRead, BookRead
from library_service.models.db import Author, Book, Genre, AuthorBookLink, GenreBookLink
from library_service.models.dto import AuthorRead, BookRead, GenreRead
router = APIRouter(tags=["relations"])
# Add author to book
@router.post("/relationships", response_model=AuthorBookLink)
@router.post("/relationships/author-book", response_model=AuthorBookLink)
def add_author_to_book(author_id: int, book_id: int, session: Session = Depends(get_session)):
author = session.get(Author, author_id)
if not author:
@@ -35,7 +35,7 @@ def add_author_to_book(author_id: int, book_id: int, session: Session = Depends(
return link
# Remove author from book
@router.delete("/relationships", response_model=Dict[str, str])
@router.delete("/relationships/author-book", response_model=Dict[str, str])
def remove_author_from_book(author_id: int, book_id: int, session: Session = Depends(get_session)):
link = session.exec(
select(AuthorBookLink)
@@ -51,7 +51,7 @@ def remove_author_from_book(author_id: int, book_id: int, session: Session = Dep
return {"message": "Relationship removed successfully"}
# Get relationships
@router.get("/relationships", response_model=List[AuthorBookLink])
@router.get("/relationships/author-book", response_model=List[AuthorBookLink])
def get_relationships(session: Session = Depends(get_session)):
relationships = session.exec(select(AuthorBookLink)).all()
return relationships

View File

@@ -24,6 +24,10 @@ def get_app() -> FastAPI:
"name": "books",
"description": "Operations with books.",
},
{
"name": "genres",
"description": "Operations with genres.",
},
{
"name": "relations",
"description": "Operations with relations.",