From 91a38a3f4aa9327481bbdef64d6acd6190772d5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Busch?= Date: Fri, 27 Jan 2023 19:57:20 +0100 Subject: [PATCH 1/5] Move recipe validations from RecipeSummary to Recipe --- mealie/schema/recipe/recipe.py | 48 ++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/mealie/schema/recipe/recipe.py b/mealie/schema/recipe/recipe.py index 4860015110..5a22e29c18 100644 --- a/mealie/schema/recipe/recipe.py +++ b/mealie/schema/recipe/recipe.py @@ -103,29 +103,9 @@ class RecipeSummary(MealieModel): class Config: orm_mode = True - @validator("tags", always=True, pre=True, allow_reuse=True) - def validate_tags(cats: list[Any]): # type: ignore - if isinstance(cats, list) and cats and isinstance(cats[0], str): - return [RecipeTag(id=uuid4(), name=c, slug=slugify(c)) for c in cats] - return cats - - @validator("recipe_category", always=True, pre=True, allow_reuse=True) - def validate_categories(cats: list[Any]): # type: ignore - if isinstance(cats, list) and cats and isinstance(cats[0], str): - return [RecipeCategory(id=uuid4(), name=c, slug=slugify(c)) for c in cats] - return cats - - @validator("group_id", always=True, pre=True, allow_reuse=True) - def validate_group_id(group_id: Any): - if isinstance(group_id, int): - return uuid4() - return group_id - @validator("user_id", always=True, pre=True, allow_reuse=True) - def validate_user_id(user_id: Any): - if isinstance(user_id, int): - return uuid4() - return user_id +class RecipeSummaryWithIngredients(RecipeSummary): + recipe_ingredient: list[RecipeIngredient] | None = [] class RecipePaginationQuery(PaginationQuery): @@ -205,6 +185,30 @@ def validate_ingredients(recipe_ingredient, values): return recipe_ingredient + @validator("tags", always=True, pre=True, allow_reuse=True) + def validate_tags(cats: list[Any]): # type: ignore + if isinstance(cats, list) and cats and isinstance(cats[0], str): + return [RecipeTag(id=uuid4(), name=c, slug=slugify(c)) for c in cats] + return cats + + @validator("recipe_category", always=True, pre=True, allow_reuse=True) + def validate_categories(cats: list[Any]): # type: ignore + if isinstance(cats, list) and cats and isinstance(cats[0], str): + return [RecipeCategory(id=uuid4(), name=c, slug=slugify(c)) for c in cats] + return cats + + @validator("group_id", always=True, pre=True, allow_reuse=True) + def validate_group_id(group_id: Any): + if isinstance(group_id, int): + return uuid4() + return group_id + + @validator("user_id", always=True, pre=True, allow_reuse=True) + def validate_user_id(user_id: Any): + if isinstance(user_id, int): + return uuid4() + return user_id + from mealie.schema.recipe.recipe_ingredient import RecipeIngredient # noqa: E402 From 8ada9292919e28dd231860e705604ca840bfa3e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Busch?= Date: Fri, 27 Jan 2023 20:00:10 +0100 Subject: [PATCH 2/5] fix RepositoryRecipes loading recipes with ingredients even when load_food is False --- mealie/repos/repository_recipes.py | 17 +++++++++++++---- mealie/routes/recipe/recipe_crud_routes.py | 12 ++++++++++-- mealie/schema/recipe/recipe.py | 3 +-- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/mealie/repos/repository_recipes.py b/mealie/repos/repository_recipes.py index 0f780ee7d3..88a1faeb21 100644 --- a/mealie/repos/repository_recipes.py +++ b/mealie/repos/repository_recipes.py @@ -16,9 +16,15 @@ from mealie.db.models.recipe.tool import Tool from mealie.schema.cookbook.cookbook import ReadCookBook from mealie.schema.recipe import Recipe -from mealie.schema.recipe.recipe import RecipeCategory, RecipePagination, RecipeSummary, RecipeTag, RecipeTool +from mealie.schema.recipe.recipe import ( + RecipeCategory, + RecipeSummary, + RecipeSummaryWithIngredients, + RecipeTag, + RecipeTool, +) from mealie.schema.recipe.recipe_category import CategoryBase, TagBase -from mealie.schema.response.pagination import PaginationQuery +from mealie.schema.response.pagination import PaginationBase, PaginationQuery from .repository_generic import RepositoryGeneric @@ -139,7 +145,7 @@ def page_all( categories: list[UUID4 | str] | None = None, tags: list[UUID4 | str] | None = None, tools: list[UUID4 | str] | None = None, - ) -> RecipePagination: + ) -> PaginationBase[RecipeSummary]: q = self.session.query(self.model) args = [ @@ -150,6 +156,9 @@ def page_all( if load_food: args.append(joinedload(RecipeModel.recipe_ingredient).options(joinedload(RecipeIngredient.food))) + item_class = RecipeSummaryWithIngredients + else: + item_class = RecipeSummary q = q.options(*args) @@ -201,7 +210,7 @@ def page_all( self.session.rollback() raise e - return RecipePagination( + return PaginationBase[item_class]( page=pagination.page, per_page=pagination.per_page, total=count, diff --git a/mealie/routes/recipe/recipe_crud_routes.py b/mealie/routes/recipe/recipe_crud_routes.py index 8a838cb2a3..0cac5eec9b 100644 --- a/mealie/routes/recipe/recipe_crud_routes.py +++ b/mealie/routes/recipe/recipe_crud_routes.py @@ -25,13 +25,21 @@ from mealie.routes._base.routers import MealieCrudRoute, UserAPIRouter from mealie.schema.cookbook.cookbook import ReadCookBook from mealie.schema.recipe import Recipe, RecipeImageTypes, ScrapeRecipe -from mealie.schema.recipe.recipe import CreateRecipe, CreateRecipeByUrlBulk, RecipePagination, RecipePaginationQuery +from mealie.schema.recipe.recipe import ( + CreateRecipe, + CreateRecipeByUrlBulk, + RecipePagination, + RecipePaginationQuery, + RecipeSummary, + RecipeSummaryWithIngredients, +) from mealie.schema.recipe.recipe_asset import RecipeAsset from mealie.schema.recipe.recipe_ingredient import RecipeIngredient from mealie.schema.recipe.recipe_scraper import ScrapeRecipeTest from mealie.schema.recipe.recipe_settings import RecipeSettings from mealie.schema.recipe.recipe_step import RecipeStep from mealie.schema.recipe.request_helpers import RecipeDuplicate, RecipeZipTokenResponse, UpdateImageResponse +from mealie.schema.response import PaginationBase from mealie.schema.response.responses import ErrorResponse from mealie.services import urls from mealie.services.event_bus_service.event_types import ( @@ -232,7 +240,7 @@ def create_recipe_from_zip(self, temp_path=Depends(temporary_zip_path), archive: # ================================================================================================================== # CRUD Operations - @router.get("", response_model=RecipePagination) + @router.get("", response_model=PaginationBase[RecipeSummary | RecipeSummaryWithIngredients]) def get_all( self, request: Request, diff --git a/mealie/schema/recipe/recipe.py b/mealie/schema/recipe/recipe.py index 5a22e29c18..f3b4c94df7 100644 --- a/mealie/schema/recipe/recipe.py +++ b/mealie/schema/recipe/recipe.py @@ -91,8 +91,6 @@ class RecipeSummary(MealieModel): rating: int | None org_url: str | None = Field(None, alias="orgURL") - recipe_ingredient: list[RecipeIngredient] | None = [] - date_added: datetime.date | None date_updated: datetime.datetime | None @@ -213,4 +211,5 @@ def validate_user_id(user_id: Any): from mealie.schema.recipe.recipe_ingredient import RecipeIngredient # noqa: E402 RecipeSummary.update_forward_refs() +RecipeSummaryWithIngredients.update_forward_refs() Recipe.update_forward_refs() From 3bd01f948734ed911c79c34232b89613b112422f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Busch?= Date: Fri, 27 Jan 2023 20:08:02 +0100 Subject: [PATCH 3/5] Add eager loading of ingredient units --- mealie/repos/repository_recipes.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mealie/repos/repository_recipes.py b/mealie/repos/repository_recipes.py index 88a1faeb21..99ba527393 100644 --- a/mealie/repos/repository_recipes.py +++ b/mealie/repos/repository_recipes.py @@ -156,6 +156,7 @@ def page_all( if load_food: args.append(joinedload(RecipeModel.recipe_ingredient).options(joinedload(RecipeIngredient.food))) + args.append(joinedload(RecipeModel.recipe_ingredient).options(joinedload(RecipeIngredient.unit))) item_class = RecipeSummaryWithIngredients else: item_class = RecipeSummary From 3f7c5d7417715a86b18743cf5d1a88eaae186f09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Busch?= Date: Fri, 27 Jan 2023 20:39:20 +0100 Subject: [PATCH 4/5] fix trying to instantiate PaginationBase with concrete type not being valid for mypy --- mealie/repos/repository_recipes.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mealie/repos/repository_recipes.py b/mealie/repos/repository_recipes.py index 99ba527393..c777e7a287 100644 --- a/mealie/repos/repository_recipes.py +++ b/mealie/repos/repository_recipes.py @@ -1,5 +1,5 @@ from random import randint -from typing import Any +from typing import Any, Type from uuid import UUID from pydantic import UUID4 @@ -211,12 +211,13 @@ def page_all( self.session.rollback() raise e - return PaginationBase[item_class]( + items = [item_class.from_orm(item) for item in data] + return PaginationBase( page=pagination.page, per_page=pagination.per_page, total=count, total_pages=total_pages, - items=data, + items=items, ) def get_by_categories(self, categories: list[RecipeCategory]) -> list[RecipeSummary]: From 531d10b5d4fb7a3c50c621a5e9abd27fc33cb971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Busch?= Date: Fri, 27 Jan 2023 20:46:03 +0100 Subject: [PATCH 5/5] fix linting issue --- mealie/repos/repository_recipes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mealie/repos/repository_recipes.py b/mealie/repos/repository_recipes.py index c777e7a287..5776284265 100644 --- a/mealie/repos/repository_recipes.py +++ b/mealie/repos/repository_recipes.py @@ -1,5 +1,5 @@ from random import randint -from typing import Any, Type +from typing import Any from uuid import UUID from pydantic import UUID4