Coverage for app / models / book.py: 97%
32 statements
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-06 04:49 +0000
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-06 04:49 +0000
1"""
2This module defines the Book model, representing book records in the database.
4The Book class includes fields for storing details such as title, author, rating,
5description, and relationships to other entities like reading statuses, feedbacks,
6and lists. It supports converting an instance to a dictionary for easier
7manipulation and provides a clean string representation.
8"""
9from sqlalchemy.orm import Mapped, mapped_column, relationship
11from app import db
12from app.models.feedback import Feedback
13from app.models.tags import TagBook
14from app.models.reading_status import ReadingStatus
17class Book(db.Model):
18 """
19 Represents a book entity in the database.
21 This class is mapped to the `books` table in the database and is used to store
22 and manage information about books such as title, author, description, and related attributes.
23 The class provides methods to convert its instance to a dictionary and to return a string
24 representation of the object.
26 :ivar id: Unique identifier for the book.
27 :type id: int
28 :ivar author: Name of the author of the book.
29 :type author: str
30 :ivar title: Title of the book.
31 :type title: str
32 :ivar asin: Amazon Standard Identification Number (ASIN) of the book,
33 if available.
34 :type asin: Optional[str]
35 :ivar link: URL linking to the book's details, if available.
36 :type link: Optional[str]
37 :ivar image: URL linking to the book's image, if available.
38 :type image: Optional[str]
39 :ivar categories_flat: Flattened string representation of the
40 book's categories, if available.
41 :type categories_flat: Optional[str]
42 :ivar book_description: Description of the book, if available.
43 :type book_description: Optional[str]
44 :ivar rating: Rating of the book, defaults to 0.0.
45 :type rating: float
46 :ivar isbn_13: International Standard Book Number (13-digit),
47 if available.
48 :type isbn_13: Optional[str]
49 :ivar isbn_10: International Standard Book Number (10-digit),
50 if available.
51 :type isbn_10: Optional[str]
52 :ivar hardcover: Indicates hardcover details of the book, if available.
53 :type hardcover: Optional[str]
54 :ivar bestsellers_rank_flat: Flattened string representation of the book's
55 bestsellers rank, if available.
56 :type bestsellers_rank_flat: Optional[str]
57 :ivar specifications_flat: Flattened string representation of the book's
58 specifications, if available.
59 :type specifications_flat: Optional[str]
60 """
61 __tablename__ = 'books'
63 id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
64 author: Mapped[str] = mapped_column(db.String(255), nullable=False, index=True)
65 title: Mapped[str] = mapped_column(db.String(255), nullable=False, index=True)
66 asin: Mapped[str | None] = mapped_column(db.String(20), index=True, nullable=True)
67 link: Mapped[str | None] = mapped_column(db.Text, nullable=True)
68 image: Mapped[str | None] = mapped_column(db.Text, nullable=True)
69 categories_flat: Mapped[str | None] = mapped_column(db.String(255), index=True, nullable=True)
70 book_description: Mapped[str | None] = mapped_column(db.Text, nullable=True)
71 rating: Mapped[float] = mapped_column(db.Float, default=0.0, index=True, nullable=False)
72 isbn_13: Mapped[str | None] = mapped_column(db.String(17), index=True, nullable=True)
73 isbn_10: Mapped[str | None] = mapped_column(db.String(13), index=True, nullable=True)
74 hardcover: Mapped[str | None] = mapped_column(db.String(64), nullable=True)
75 bestsellers_rank_flat: Mapped[str | None] = mapped_column(db.Text, nullable=True)
76 specifications_flat: Mapped[str | None] = mapped_column(db.Text, nullable=True)
78 reading_statuses: Mapped[list["ReadingStatus"]] = relationship(back_populates="book")
79 feedbacks: Mapped[list["Feedback"]] = relationship(back_populates="book")
81 # Relationship to TagBook, connects with ListBook.book
82 tags: Mapped[list['TagBook']] = relationship('TagBook',
83 back_populates='book',
84 cascade='all, delete-orphan')
86 def to_dict(self) -> dict:
87 """Converts the model instance into a dictionary."""
88 result = {column.name: getattr(self, column.name) for column in self.__table__.columns}
89 if result.get('book_description'):
90 # some descriptions have and these need to be rendered as just space
91 result['book_description'] = result['book_description'].replace('\u00A0', '\u0020')
92 return result
94 def __repr__(self) -> str:
95 """Provides a clean string representation of the object."""
96 return f"<Book(id={self.id}, title='{self.title}', author='{self.author}')>"
99__all__ = ["Book"]