Coverage for opt/mealie/lib/python3.12/site-packages/mealie/db/models/recipe/category.py: 91%

33 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-11-25 15:48 +0000

1from typing import TYPE_CHECKING 1a

2 

3import sqlalchemy as sa 1a

4import sqlalchemy.orm as orm 1a

5from slugify import slugify 1a

6from sqlalchemy.orm import Mapped, mapped_column, validates 1a

7 

8from mealie.core import root_logger 1a

9 

10from .._model_base import BaseMixins, SqlAlchemyBase 1a

11from .._model_utils.guid import GUID 1a

12 

13if TYPE_CHECKING: 13 ↛ 14line 13 didn't jump to line 14 because the condition on line 13 was never true1a

14 from ..group import Group 

15 from . import RecipeModel 

16logger = root_logger.get_logger() 1a

17 

18 

19group_to_categories = sa.Table( 1a

20 "group_to_categories", 

21 SqlAlchemyBase.metadata, 

22 sa.Column("group_id", GUID, sa.ForeignKey("groups.id"), index=True), 

23 sa.Column("category_id", GUID, sa.ForeignKey("categories.id"), index=True), 

24 sa.UniqueConstraint("group_id", "category_id", name="group_id_category_id_key"), 

25) 

26 

27plan_rules_to_categories = sa.Table( 1a

28 "plan_rules_to_categories", 

29 SqlAlchemyBase.metadata, 

30 sa.Column("group_plan_rule_id", GUID, sa.ForeignKey("group_meal_plan_rules.id"), index=True), 

31 sa.Column("category_id", GUID, sa.ForeignKey("categories.id"), index=True), 

32 sa.UniqueConstraint("group_plan_rule_id", "category_id", name="group_plan_rule_id_category_id_key"), 

33) 

34 

35recipes_to_categories = sa.Table( 1a

36 "recipes_to_categories", 

37 SqlAlchemyBase.metadata, 

38 sa.Column("recipe_id", GUID, sa.ForeignKey("recipes.id"), index=True), 

39 sa.Column("category_id", GUID, sa.ForeignKey("categories.id"), index=True), 

40 sa.UniqueConstraint("recipe_id", "category_id", name="recipe_id_category_id_key"), 

41) 

42 

43cookbooks_to_categories = sa.Table( 1a

44 "cookbooks_to_categories", 

45 SqlAlchemyBase.metadata, 

46 sa.Column("cookbook_id", GUID, sa.ForeignKey("cookbooks.id"), index=True), 

47 sa.Column("category_id", GUID, sa.ForeignKey("categories.id"), index=True), 

48 sa.UniqueConstraint("cookbook_id", "category_id", name="cookbook_id_category_id_key"), 

49) 

50 

51 

52class Category(SqlAlchemyBase, BaseMixins): 1a

53 __tablename__ = "categories" 1a

54 __table_args__ = (sa.UniqueConstraint("slug", "group_id", name="category_slug_group_id_key"),) 1a

55 

56 # ID Relationships 

57 group_id: Mapped[GUID] = mapped_column(GUID, sa.ForeignKey("groups.id"), nullable=False, index=True) 1a

58 group: Mapped["Group"] = orm.relationship("Group", back_populates="categories", foreign_keys=[group_id]) 1a

59 

60 id: Mapped[GUID] = mapped_column(GUID, primary_key=True, default=GUID.generate) 1a

61 name: Mapped[str] = mapped_column(sa.String, index=True, nullable=False) 1a

62 slug: Mapped[str] = mapped_column(sa.String, index=True, nullable=False) 1a

63 recipes: Mapped[list["RecipeModel"]] = orm.relationship( 1a

64 "RecipeModel", secondary=recipes_to_categories, back_populates="recipe_category" 

65 ) 

66 

67 @validates("name") 1a

68 def validate_name(self, key, name): 1a

69 assert name != "" 

70 return name 

71 

72 def __init__(self, name, group_id, **_) -> None: 1a

73 self.group_id = group_id 

74 self.name = name.strip() 

75 self.slug = slugify(name)