recipe-inator/backend/app/models.py

101 lines
4.3 KiB
Python

from datetime import datetime, timezone
from sqlalchemy import DateTime, ForeignKey, Integer, String, Text, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.database import Base
def _utcnow() -> datetime:
return datetime.now(timezone.utc)
class Recipe(Base):
__tablename__ = "recipes"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
name: Mapped[str] = mapped_column(String(255), nullable=False)
slug: Mapped[str] = mapped_column(String(255), unique=True, nullable=False, index=True)
category: Mapped[str | None] = mapped_column(String(100), nullable=True)
image_filename: Mapped[str | None] = mapped_column(String(255), nullable=True)
preptime: Mapped[str | None] = mapped_column(String(100), nullable=True)
cooktime: Mapped[str | None] = mapped_column(String(100), nullable=True)
baketime: Mapped[str | None] = mapped_column(String(100), nullable=True)
cooltime: Mapped[str | None] = mapped_column(String(100), nullable=True)
marinade_time: Mapped[str | None] = mapped_column(String(100), nullable=True)
robot_time: Mapped[str | None] = mapped_column(String(100), nullable=True)
servings: Mapped[str | None] = mapped_column(String(50), nullable=True)
notes: Mapped[str | None] = mapped_column(Text, nullable=True)
kcal: Mapped[str | None] = mapped_column(String(50), nullable=True)
kh: Mapped[str | None] = mapped_column(String(50), nullable=True)
protein: Mapped[str | None] = mapped_column(String(50), nullable=True)
fett: Mapped[str | None] = mapped_column(String(50), nullable=True)
created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=_utcnow)
updated_at: Mapped[datetime] = mapped_column(
DateTime(timezone=True), default=_utcnow, onupdate=_utcnow
)
ingredients: Mapped[list["Ingredient"]] = relationship(
back_populates="recipe", cascade="all, delete-orphan", order_by="Ingredient.position"
)
steps: Mapped[list["Step"]] = relationship(
back_populates="recipe", cascade="all, delete-orphan", order_by="Step.position"
)
book_links: Mapped[list["BookRecipe"]] = relationship(
back_populates="recipe", cascade="all, delete-orphan"
)
class Ingredient(Base):
__tablename__ = "ingredients"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
recipe_id: Mapped[int] = mapped_column(ForeignKey("recipes.id"), nullable=False)
position: Mapped[int] = mapped_column(Integer, nullable=False)
kind: Mapped[str] = mapped_column(String(20), nullable=False, default="item") # item | section_header
quantity: Mapped[str | None] = mapped_column(String(50), nullable=True)
unit: Mapped[str | None] = mapped_column(String(50), nullable=True)
text: Mapped[str] = mapped_column(String(255), nullable=False)
recipe: Mapped["Recipe"] = relationship(back_populates="ingredients")
class Step(Base):
__tablename__ = "steps"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
recipe_id: Mapped[int] = mapped_column(ForeignKey("recipes.id"), nullable=False)
position: Mapped[int] = mapped_column(Integer, nullable=False)
text: Mapped[str] = mapped_column(Text, nullable=False)
recipe: Mapped["Recipe"] = relationship(back_populates="steps")
class Book(Base):
__tablename__ = "books"
id: Mapped[int] = mapped_column(Integer, primary_key=True)
name: Mapped[str] = mapped_column(String(255), nullable=False)
description: Mapped[str | None] = mapped_column(Text, nullable=True)
recipe_links: Mapped[list["BookRecipe"]] = relationship(
back_populates="book", cascade="all, delete-orphan"
)
class BookRecipe(Base):
__tablename__ = "book_recipes"
__table_args__ = (UniqueConstraint("book_id", "recipe_id", name="uq_book_recipe"),)
id: Mapped[int] = mapped_column(Integer, primary_key=True)
book_id: Mapped[int] = mapped_column(ForeignKey("books.id"), nullable=False)
recipe_id: Mapped[int] = mapped_column(ForeignKey("recipes.id"), nullable=False)
chapter: Mapped[str | None] = mapped_column(String(100), nullable=True)
position: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
book: Mapped["Book"] = relationship(back_populates="recipe_links")
recipe: Mapped["Recipe"] = relationship(back_populates="book_links")