Coverage for opt/mealie/lib/python3.12/site-packages/mealie/db/models/recipe/tag.py: 91%
32 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 03:04 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 03:04 +0000
1from typing import TYPE_CHECKING
3import sqlalchemy as sa
4import sqlalchemy.orm as orm
5from slugify import slugify
6from sqlalchemy.orm import Mapped, mapped_column, validates
8from mealie.core import root_logger
9from mealie.db.models._model_base import BaseMixins, SqlAlchemyBase
10from mealie.db.models._model_utils import guid
12if TYPE_CHECKING: 12 ↛ 13line 12 didn't jump to line 13 because the condition on line 12 was never true
13 from ..group import Group
14 from . import RecipeModel
17logger = root_logger.get_logger()
19recipes_to_tags = sa.Table(
20 "recipes_to_tags",
21 SqlAlchemyBase.metadata,
22 sa.Column("recipe_id", guid.GUID, sa.ForeignKey("recipes.id"), index=True),
23 sa.Column("tag_id", guid.GUID, sa.ForeignKey("tags.id"), index=True),
24 sa.UniqueConstraint("recipe_id", "tag_id", name="recipe_id_tag_id_key"),
25)
27plan_rules_to_tags = sa.Table(
28 "plan_rules_to_tags",
29 SqlAlchemyBase.metadata,
30 sa.Column("plan_rule_id", guid.GUID, sa.ForeignKey("group_meal_plan_rules.id"), index=True),
31 sa.Column("tag_id", guid.GUID, sa.ForeignKey("tags.id"), index=True),
32 sa.UniqueConstraint("plan_rule_id", "tag_id", name="plan_rule_id_tag_id_key"),
33)
35cookbooks_to_tags = sa.Table(
36 "cookbooks_to_tags",
37 SqlAlchemyBase.metadata,
38 sa.Column("cookbook_id", guid.GUID, sa.ForeignKey("cookbooks.id"), index=True),
39 sa.Column("tag_id", guid.GUID, sa.ForeignKey("tags.id"), index=True),
40 sa.UniqueConstraint("cookbook_id", "tag_id", name="cookbook_id_tag_id_key"),
41)
44class Tag(SqlAlchemyBase, BaseMixins):
45 __tablename__ = "tags"
46 __table_args__ = (sa.UniqueConstraint("slug", "group_id", name="tags_slug_group_id_key"),)
47 id: Mapped[guid.GUID] = mapped_column(guid.GUID, primary_key=True, default=guid.GUID.generate)
49 # ID Relationships
50 group_id: Mapped[guid.GUID] = mapped_column(guid.GUID, sa.ForeignKey("groups.id"), nullable=False, index=True)
51 group: Mapped["Group"] = orm.relationship("Group", back_populates="tags", foreign_keys=[group_id])
53 name: Mapped[str] = mapped_column(sa.String, index=True, nullable=False)
54 slug: Mapped[str] = mapped_column(sa.String, index=True, nullable=False)
55 recipes: Mapped[list["RecipeModel"]] = orm.relationship(
56 "RecipeModel", secondary=recipes_to_tags, back_populates="tags"
57 )
59 @validates("name")
60 def validate_name(self, key, name):
61 assert name != ""
62 return name
64 def __init__(self, name, group_id, **_) -> None:
65 self.group_id = group_id
66 self.name = name.strip()
67 self.slug = slugify(self.name)