diff --git a/mealie/schema/group/group_shopping_list.py b/mealie/schema/group/group_shopping_list.py index d91f79e90b29..ae5a27da5ece 100644 --- a/mealie/schema/group/group_shopping_list.py +++ b/mealie/schema/group/group_shopping_list.py @@ -2,7 +2,7 @@ from __future__ import annotations from datetime import datetime -from pydantic import UUID4, ConfigDict, field_validator +from pydantic import UUID4, ConfigDict, field_validator, model_validator from sqlalchemy.orm import joinedload, selectinload from sqlalchemy.orm.interfaces import LoaderOption @@ -100,14 +100,15 @@ class ShoppingListItemOut(ShoppingListItemBase): created_at: datetime | None = None update_at: datetime | None = None - def __init__(self, **kwargs): - super().__init__(**kwargs) - + @model_validator(mode="after") + def post_validate(self): # if we're missing a label, but the food has a label, use that as the label if (not self.label) and (self.food and self.food.label): self.label = self.food.label self.label_id = self.label.id + return self + model_config = ConfigDict(from_attributes=True) @classmethod diff --git a/mealie/schema/recipe/recipe.py b/mealie/schema/recipe/recipe.py index 7bf253e8de22..483247d07f20 100644 --- a/mealie/schema/recipe/recipe.py +++ b/mealie/schema/recipe/recipe.py @@ -6,7 +6,7 @@ from pathlib import Path from typing import Annotated, Any, ClassVar from uuid import uuid4 -from pydantic import UUID4, BaseModel, ConfigDict, Field, field_validator +from pydantic import UUID4, BaseModel, ConfigDict, Field, field_validator, model_validator from pydantic_core.core_schema import ValidationInfo from slugify import slugify from sqlalchemy import Select, desc, func, or_, select, text @@ -183,17 +183,8 @@ class Recipe(RecipeSummary): model_config = ConfigDict(from_attributes=True) - @classmethod - def model_validate(cls, obj): - recipe = super().model_validate(obj) - recipe.__post_init__() - return recipe - - def __init__(self, **kwargs) -> None: - super().__init__(**kwargs) - self.__post_init__() - - def __post_init__(self) -> None: + @model_validator(mode="after") + def post_validate(self): # the ingredient disable_amount property is unreliable, # so we set it here and recalculate the display property disable_amount = self.settings.disable_amount if self.settings else True @@ -202,6 +193,8 @@ class Recipe(RecipeSummary): ingredient.is_food = not ingredient.disable_amount ingredient.display = ingredient._format_display() + return self + @field_validator("slug", mode="before") def validate_slug(slug: str, info: ValidationInfo): if not info.data.get("name"): diff --git a/mealie/schema/recipe/recipe_ingredient.py b/mealie/schema/recipe/recipe_ingredient.py index 8a260a6e43a1..2d0ec633dace 100644 --- a/mealie/schema/recipe/recipe_ingredient.py +++ b/mealie/schema/recipe/recipe_ingredient.py @@ -6,7 +6,7 @@ from fractions import Fraction from typing import ClassVar from uuid import UUID, uuid4 -from pydantic import UUID4, ConfigDict, Field, field_validator +from pydantic import UUID4, ConfigDict, Field, field_validator, model_validator from sqlalchemy.orm import joinedload from sqlalchemy.orm.interfaces import LoaderOption @@ -31,6 +31,7 @@ def display_fraction(fraction: Fraction): class UnitFoodBase(MealieModel): + id: UUID4 | None = None name: str plural_name: str | None = None description: str = "" @@ -134,9 +135,8 @@ class RecipeIngredientBase(MealieModel): Automatically calculated after the object is created, unless overwritten """ - def __init__(self, **kwargs) -> None: - super().__init__(**kwargs) - + @model_validator(mode="after") + def post_validate(self): # calculate missing is_food and disable_amount values # we can't do this in a validator since they depend on each other if self.is_food is None and self.disable_amount is not None: @@ -151,6 +151,8 @@ class RecipeIngredientBase(MealieModel): if not self.display: self.display = self._format_display() + return self + @field_validator("unit", mode="before") @classmethod def validate_unit(cls, v):