Coverage for opt/mealie/lib/python3.12/site-packages/mealie/db/models/household/household.py: 88%

39 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-07 03:04 +0000

1from typing import TYPE_CHECKING 

2 

3import sqlalchemy as sa 

4import sqlalchemy.orm as orm 

5from pydantic import ConfigDict 

6from sqlalchemy.orm import Mapped, mapped_column 

7 

8from .._model_base import BaseMixins, SqlAlchemyBase 

9from .._model_utils.auto_init import auto_init 

10from .._model_utils.guid import GUID 

11from ..recipe.ingredient import households_to_ingredient_foods 

12from ..recipe.tool import households_to_tools 

13from .household_to_recipe import HouseholdToRecipe 

14 

15if TYPE_CHECKING: 15 ↛ 16line 15 didn't jump to line 16 because the condition on line 15 was never true

16 from ..group import Group 

17 from ..recipe import IngredientFoodModel, RecipeModel, Tool 

18 from ..users import User 

19 from . import ( 

20 CookBook, 

21 GroupEventNotifierModel, 

22 GroupInviteToken, 

23 GroupRecipeAction, 

24 GroupWebhooksModel, 

25 HouseholdPreferencesModel, 

26 ) 

27 

28 

29class Household(SqlAlchemyBase, BaseMixins): 

30 __tablename__ = "households" 

31 __table_args__ = ( 

32 sa.UniqueConstraint("group_id", "name", name="household_name_group_id_key"), 

33 sa.UniqueConstraint("group_id", "slug", name="household_slug_group_id_key"), 

34 ) 

35 

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

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

38 slug: Mapped[str | None] = mapped_column(sa.String, index=True) 

39 

40 invite_tokens: Mapped[list["GroupInviteToken"]] = orm.relationship( 

41 "GroupInviteToken", back_populates="household", cascade="all, delete-orphan" 

42 ) 

43 preferences: Mapped["HouseholdPreferencesModel"] = orm.relationship( 

44 "HouseholdPreferencesModel", 

45 back_populates="household", 

46 uselist=False, 

47 single_parent=True, 

48 cascade="all, delete-orphan", 

49 ) 

50 

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

52 group: Mapped["Group"] = orm.relationship("Group", back_populates="households") 

53 users: Mapped[list["User"]] = orm.relationship("User", back_populates="household") 

54 

55 COMMON_ARGS = { 

56 "back_populates": "household", 

57 "cascade": "all, delete-orphan", 

58 "single_parent": True, 

59 } 

60 

61 recipe_actions: Mapped[list["GroupRecipeAction"]] = orm.relationship("GroupRecipeAction", **COMMON_ARGS) 

62 cookbooks: Mapped[list["CookBook"]] = orm.relationship("CookBook", **COMMON_ARGS) 

63 

64 webhooks: Mapped[list["GroupWebhooksModel"]] = orm.relationship("GroupWebhooksModel", **COMMON_ARGS) 

65 group_event_notifiers: Mapped[list["GroupEventNotifierModel"]] = orm.relationship( 

66 "GroupEventNotifierModel", **COMMON_ARGS 

67 ) 

68 

69 made_recipes: Mapped[list["RecipeModel"]] = orm.relationship( 

70 "RecipeModel", secondary=HouseholdToRecipe.__tablename__, back_populates="made_by" 

71 ) 

72 ingredient_foods_on_hand: Mapped[list["IngredientFoodModel"]] = orm.relationship( 

73 "IngredientFoodModel", 

74 secondary=households_to_ingredient_foods, 

75 back_populates="households_with_ingredient_food", 

76 ) 

77 tools_on_hand: Mapped[list["Tool"]] = orm.relationship( 

78 "Tool", secondary=households_to_tools, back_populates="households_with_tool" 

79 ) 

80 

81 model_config = ConfigDict( 

82 exclude={ 

83 "users", 

84 "webhooks", 

85 "recipe_actions", 

86 "cookbooks", 

87 "preferences", 

88 "invite_tokens", 

89 "group_event_notifiers", 

90 "group", 

91 "made_recipes", 

92 } 

93 ) 

94 

95 @auto_init() 

96 def __init__(self, **_) -> None: 

97 pass