feat: Add DELETE /{slug}/image (#6259)

Co-authored-by: Michael Genson <71845777+michael-genson@users.noreply.github.com>
This commit is contained in:
Christian Hollinger
2025-11-03 20:41:54 -05:00
committed by GitHub
parent 7bb0f0801a
commit bb67d993a0
12 changed files with 150 additions and 16 deletions

View File

@@ -5,6 +5,7 @@
"recipe": {
"unique-name-error": "Recipe names must be unique",
"recipe-created": "Recipe Created",
"recipe-image-deleted": "Recipe image deleted",
"recipe-defaults": {
"ingredient-note": "1 Cup Flour",
"step-text": "Recipe steps as well as other fields in the recipe page support markdown syntax.\n\n**Add a link**\n\n[My Link](https://demo.mealie.io)\n"

View File

@@ -154,6 +154,11 @@ class RepositoryRecipes(HouseholdRepositoryGeneric[Recipe, RecipeModel]):
return entry.image
def delete_image(self, slug: str, _: str | None = None):
entry: RecipeModel = self._query_one(match_value=slug)
entry.image = None
self.session.commit()
def count_uncategorized(self, count=True, override_schema=None):
return self._count_attribute(
attribute_name=RecipeModel.recipe_category,

View File

@@ -46,7 +46,7 @@ from mealie.schema.recipe.request_helpers import (
)
from mealie.schema.response import PaginationBase, PaginationQuery
from mealie.schema.response.pagination import RecipeSearchQuery
from mealie.schema.response.responses import ErrorResponse
from mealie.schema.response.responses import ErrorResponse, SuccessResponse
from mealie.services import urls
from mealie.services.event_bus_service.event_types import (
EventOperation,
@@ -543,6 +543,15 @@ class RecipeController(BaseRecipeController):
self.handle_exceptions(e)
return None
@router.delete("/{slug}/image", tags=["Recipe: Images and Assets"])
def delete_recipe_image(self, slug: str):
try:
self.service.delete_recipe_image(slug)
return SuccessResponse.respond(message=self.t("recipe.recipe-image-deleted"))
except Exception as e:
self.handle_exceptions(e)
return None
@router.post("/{slug}/assets", response_model=RecipeAsset, tags=["Recipe: Images and Assets"])
def upload_recipe_asset(
self,

View File

@@ -8,6 +8,7 @@ from pydantic import UUID4
from mealie.pkgs import img, safehttp
from mealie.pkgs.safehttp.transport import AsyncSafeTransport
from mealie.schema.recipe.recipe import Recipe
from mealie.schema.recipe.recipe_image_types import RecipeImageTypes
from mealie.services._base_service import BaseService
from mealie.services.scraper.user_agents_manager import get_user_agents_manager
@@ -104,6 +105,14 @@ class RecipeDataService(BaseService):
return image_path
def delete_image(self, image_dir: Path | None = None):
if not image_dir:
image_dir = self.dir_image
for img_type in RecipeImageTypes:
image_path = image_dir.joinpath(img_type.value)
image_path.unlink(missing_ok=True)
async def scrape_image(self, image_url: str | dict[str, str] | list[str]) -> None:
self.logger.info(f"Image URL: {image_url}")
user_agent = get_user_agents_manager().user_agents[0]

View File

@@ -418,6 +418,17 @@ class RecipeService(RecipeServiceBase):
return self.group_recipes.update_image(slug, extension)
def delete_recipe_image(self, slug: str) -> None:
recipe = self.get_one(slug)
if not self.can_update(recipe):
raise exceptions.PermissionDenied("You do not have permission to edit this recipe.")
data_service = RecipeDataService(recipe.id)
data_service.delete_image()
self.group_recipes.delete_image(slug)
return None
def patch_one(self, slug_or_id: str | UUID, patch_data: Recipe) -> Recipe:
recipe: Recipe = self._pre_update_check(slug_or_id, patch_data)