
- Implemented CRUD operations for manga, authors, publishers, and genres - Added search and filtering functionality - Set up SQLAlchemy ORM with SQLite database - Configured Alembic for database migrations - Implemented logging with Loguru - Added comprehensive API documentation - Set up error handling and validation - Added ruff for linting and formatting
81 lines
3.1 KiB
Python
81 lines
3.1 KiB
Python
from datetime import datetime
|
|
|
|
from pydantic import BaseModel, Field, validator
|
|
|
|
from app.schemas.author import Author
|
|
from app.schemas.genre import Genre
|
|
from app.schemas.publisher import Publisher
|
|
|
|
|
|
# Shared properties
|
|
class MangaBase(BaseModel):
|
|
title: str = Field(..., min_length=1, max_length=255, description="Title of the manga")
|
|
original_title: str | None = Field(
|
|
None, max_length=255, description="Original title in Japanese or other language"
|
|
)
|
|
isbn: str | None = Field(None, max_length=20, description="ISBN of the manga volume")
|
|
description: str | None = Field(None, description="Description of the manga")
|
|
volume_number: int | None = Field(None, ge=1, description="Volume number in the series")
|
|
total_volumes: int | None = Field(
|
|
None, ge=1, description="Total number of volumes in the series"
|
|
)
|
|
publication_date: datetime | None = Field(None, description="Publication date of the manga")
|
|
page_count: int | None = Field(None, ge=1, description="Number of pages")
|
|
price: float | None = Field(None, ge=0, description="Price of the manga")
|
|
quantity: int = Field(0, ge=0, description="Quantity in inventory")
|
|
in_stock: bool = Field(True, description="Whether the manga is in stock")
|
|
rating: float | None = Field(None, ge=0, le=10, description="Rating of the manga (0-10)")
|
|
language: str | None = Field(None, max_length=50, description="Language of the manga")
|
|
cover_image_url: str | None = Field(None, max_length=255, description="URL to the cover image")
|
|
|
|
@validator("total_volumes")
|
|
def validate_total_volumes(self, v, values):
|
|
if v is not None and "volume_number" in values and values["volume_number"] is not None:
|
|
if v < values["volume_number"]:
|
|
raise ValueError("Total volumes must be greater than or equal to volume number")
|
|
return v
|
|
|
|
|
|
# Properties to receive on manga creation
|
|
class MangaCreate(MangaBase):
|
|
author_id: int | None = Field(None, description="ID of the author")
|
|
publisher_id: int | None = Field(None, description="ID of the publisher")
|
|
genre_ids: list[int] | None = Field(None, description="IDs of the genres")
|
|
|
|
|
|
# Properties to receive on manga update
|
|
class MangaUpdate(MangaBase):
|
|
title: str | None = Field(None, min_length=1, max_length=255, description="Title of the manga")
|
|
author_id: int | None = Field(None, description="ID of the author")
|
|
publisher_id: int | None = Field(None, description="ID of the publisher")
|
|
genre_ids: list[int] | None = Field(None, description="IDs of the genres")
|
|
|
|
|
|
# Properties shared by models stored in DB
|
|
class MangaInDBBase(MangaBase):
|
|
id: int
|
|
author_id: int | None
|
|
publisher_id: int | None
|
|
created_at: datetime
|
|
updated_at: datetime
|
|
|
|
class Config:
|
|
orm_mode = True
|
|
|
|
|
|
# Properties to return to client
|
|
class Manga(MangaInDBBase):
|
|
pass
|
|
|
|
|
|
# Properties properties stored in DB
|
|
class MangaInDB(MangaInDBBase):
|
|
pass
|
|
|
|
|
|
# Additional properties for response with relationships
|
|
class MangaWithRelations(Manga):
|
|
author: Author | None = None
|
|
publisher: Publisher | None = None
|
|
genres: list[Genre] = []
|