From 513c6850e4622ba0d1c014156a3102ff938c841d Mon Sep 17 00:00:00 2001 From: mariodz95 Date: Mon, 21 Jul 2025 16:16:18 +0200 Subject: [PATCH] fix: error when trying to change recipe image --- .../RecipePageInstructions.vue | 4 +-- mealie/repos/repository_generic.py | 30 ++++++++++++------- mealie/routes/_base/mixins.py | 10 +++---- mealie/routes/recipe/recipe_crud_routes.py | 9 +++--- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/frontend/components/Domain/Recipe/RecipePage/RecipePageParts/RecipePageInstructions.vue b/frontend/components/Domain/Recipe/RecipePage/RecipePageParts/RecipePageInstructions.vue index 65211b859..7cae0d999 100644 --- a/frontend/components/Domain/Recipe/RecipePage/RecipePageParts/RecipePageInstructions.vue +++ b/frontend/components/Domain/Recipe/RecipePage/RecipePageParts/RecipePageInstructions.vue @@ -393,8 +393,6 @@ const props = defineProps({ const emit = defineEmits(["click-instruction-field", "update:assets"]); -const BASE_URL = useRequestURL().origin; - const { isCookMode, toggleCookMode, isEditForm } = usePageState(props.recipe.slug); const dialog = ref(false); @@ -699,7 +697,7 @@ async function handleImageDrop(index: number, files: File[]) { } emit("update:assets", [...assets.value, data]); - const assetUrl = BASE_URL + recipeAssetPath(props.recipe.id, data.fileName as string); + const assetUrl = recipeAssetPath(props.recipe.id, data.fileName as string); const text = ``; instructionList.value[index].text += text; } diff --git a/mealie/repos/repository_generic.py b/mealie/repos/repository_generic.py index f8ab3f1b4..d53c7e584 100644 --- a/mealie/repos/repository_generic.py +++ b/mealie/repos/repository_generic.py @@ -83,12 +83,11 @@ class RepositoryGeneric[Schema: MealieModel, Model: SqlAlchemyBase]: else: return q - def _filter_builder(self, **kwargs) -> dict[str, Any]: + def _filter_builder(self, skip_household: bool = False, **kwargs) -> dict[str, Any]: dct = {} - if self.group_id: dct["group_id"] = self.group_id - if self.household_id: + if self.household_id and not skip_household: dct["household_id"] = self.household_id return {**dct, **kwargs} @@ -134,7 +133,9 @@ class RepositoryGeneric[Schema: MealieModel, Model: SqlAlchemyBase]: result = self.session.execute(q).unique().scalars().all() return [eff_schema.model_validate(x) for x in result] - def _query_one(self, match_value: str | int | UUID4, match_key: str | None = None) -> Model: + def _query_one( + self, match_value: str | int | UUID4, match_key: str | None = None, skip_household: bool = False + ) -> Model: """ Query the sql database for one item an return the sql alchemy model object. If no match key is provided the primary_key attribute will be used. @@ -142,11 +143,16 @@ class RepositoryGeneric[Schema: MealieModel, Model: SqlAlchemyBase]: if match_key is None: match_key = self.primary_key - fltr = self._filter_builder(**{match_key: match_value}) + fltr = self._filter_builder(**{match_key: match_value}, skip_household=skip_household) return self.session.execute(self._query().filter_by(**fltr)).unique().scalars().one() def get_one( - self, value: str | int | UUID4, key: str | None = None, any_case=False, override_schema=None + self, + value: str | int | UUID4, + key: str | None = None, + any_case=False, + override_schema=None, + skip_household: str = False, ) -> Schema | None: key = key or self.primary_key eff_schema = override_schema or self.schema @@ -155,9 +161,11 @@ class RepositoryGeneric[Schema: MealieModel, Model: SqlAlchemyBase]: if any_case: search_attr = getattr(self.model, key) - q = q.where(func.lower(search_attr) == str(value).lower()).filter_by(**self._filter_builder()) + q = q.where(func.lower(search_attr) == str(value).lower()).filter_by( + **self._filter_builder(skip_household=skip_household) + ) else: - q = q.filter_by(**self._filter_builder(**{key: value})) + q = q.filter_by(**self._filter_builder(**{key: value}, skip_household=skip_household)) result = self.session.execute(q).unique().scalars().one_or_none() @@ -195,7 +203,9 @@ class RepositoryGeneric[Schema: MealieModel, Model: SqlAlchemyBase]: return [self.schema.model_validate(x) for x in new_documents] - def update(self, match_value: str | int | UUID4, new_data: dict | BaseModel) -> Schema: + def update( + self, match_value: str | int | UUID4, new_data: dict | BaseModel, skip_household: bool = False + ) -> Schema: """Update a database entry. Args: session (Session): Database Session @@ -207,7 +217,7 @@ class RepositoryGeneric[Schema: MealieModel, Model: SqlAlchemyBase]: """ new_data = new_data if isinstance(new_data, dict) else new_data.model_dump() - entry = self._query_one(match_value=match_value) + entry = self._query_one(match_value=match_value, skip_household=skip_household) entry.update(session=self.session, **new_data) self.session.commit() diff --git a/mealie/routes/_base/mixins.py b/mealie/routes/_base/mixins.py index e69457c78..4ed6f4cb5 100644 --- a/mealie/routes/_base/mixins.py +++ b/mealie/routes/_base/mixins.py @@ -73,8 +73,8 @@ class HttpRepo[C: BaseModel, R: BaseModel, U: BaseModel]: return item - def get_one(self, item_id: int | str | UUID4, key: str | None = None) -> R: - item = self.repo.get_one(item_id, key) + def get_one(self, item_id: int | str | UUID4, key: str | None = None, skip_household: bool = False) -> R: + item = self.repo.get_one(item_id, key, skip_household=skip_household) if not item: raise HTTPException( @@ -84,8 +84,8 @@ class HttpRepo[C: BaseModel, R: BaseModel, U: BaseModel]: return item - def update_one(self, data: U, item_id: int | str | UUID4) -> R: - item = self.repo.get_one(item_id) + def update_one(self, data: U, item_id: int | str | UUID4, skip_household: bool = False) -> R: + item = self.repo.get_one(item_id, skip_household=skip_household) if not item: raise HTTPException( @@ -94,7 +94,7 @@ class HttpRepo[C: BaseModel, R: BaseModel, U: BaseModel]: ) try: - item = self.repo.update(item_id, data) # type: ignore + item = self.repo.update(item_id, data, skip_household=skip_household) # type: ignore except Exception as ex: self.handle_exception(ex) diff --git a/mealie/routes/recipe/recipe_crud_routes.py b/mealie/routes/recipe/recipe_crud_routes.py index 0504966c8..92a6aa46b 100644 --- a/mealie/routes/recipe/recipe_crud_routes.py +++ b/mealie/routes/recipe/recipe_crud_routes.py @@ -523,7 +523,7 @@ class RecipeController(BaseRecipeController): @router.put("/{slug}/image", response_model=UpdateImageResponse, tags=["Recipe: Images and Assets"]) def update_recipe_image(self, slug: str, image: bytes = File(...), extension: str = Form(...)): - recipe = self.mixins.get_one(slug) + recipe = self.mixins.get_one(slug, skip_household=True) data_service = RecipeDataService(recipe.id) data_service.write_image(image, extension) @@ -540,6 +540,7 @@ class RecipeController(BaseRecipeController): file: UploadFile = File(...), ): """Upload a file to store as a recipe asset""" + skip_household = True if "." in extension: extension = extension.split(".")[-1] @@ -550,7 +551,7 @@ class RecipeController(BaseRecipeController): file_name = f"{file_slug}.{extension}" asset_in = RecipeAsset(name=name, icon=icon, file_name=file_name) - recipe = self.mixins.get_one(slug) + recipe = self.mixins.get_one(slug, skip_household=skip_household) dest = recipe.asset_dir / file_name @@ -567,9 +568,9 @@ class RecipeController(BaseRecipeController): if not dest.is_file(): raise HTTPException(status.HTTP_500_INTERNAL_SERVER_ERROR) - recipe = self.mixins.get_one(slug) + recipe = self.mixins.get_one(slug, skip_household=skip_household) recipe.assets.append(asset_in) - self.mixins.update_one(recipe, slug) + self.mixins.update_one(recipe, slug, skip_household=skip_household) return asset_in