From 57983df4bd43491e30a0f71ff85c9c3e7acf210d Mon Sep 17 00:00:00 2001 From: Will Miao Date: Mon, 20 Jul 2026 11:20:06 +0800 Subject: [PATCH] fix(recipe): resolve recipe metadata update bugs in cache sort, allowed fields, and bulk API routing - Use safe .get() in RecipeCache._resort_locked instead of itemgetter to prevent KeyError when recipe missing created_date; align sort key with _sort_cache_sync (prefer modified, fallback created_date, fallback 0) - Add base_model to allowed_fields in persistence_service.update_recipe() so the field passes validation - Route bulk base model updates through updateRecipeMetadata() on recipes page instead of generic saveModelMetadata(), matching existing isRecipesPage pattern used in setBulkFavorites and saveBulkTags --- py/services/recipe_cache.py | 8 ++++++-- py/services/recipes/persistence_service.py | 3 ++- static/js/managers/BulkManager.js | 8 +++++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/py/services/recipe_cache.py b/py/services/recipe_cache.py index c0762a4a..048e8ce8 100644 --- a/py/services/recipe_cache.py +++ b/py/services/recipe_cache.py @@ -1,7 +1,6 @@ import asyncio from typing import Iterable, List, Dict, Optional from dataclasses import dataclass, field -from operator import itemgetter from natsort import natsorted @@ -149,5 +148,10 @@ class RecipeCache: ) if not name_only: self.sorted_by_date = sorted( - self.raw_data, key=itemgetter("created_date", "file_path"), reverse=True + self.raw_data, + key=lambda x: ( + x.get("modified", x.get("created_date", 0)), + x.get("file_path", ""), + ), + reverse=True, ) diff --git a/py/services/recipes/persistence_service.py b/py/services/recipes/persistence_service.py index 184268f4..6852faf5 100644 --- a/py/services/recipes/persistence_service.py +++ b/py/services/recipes/persistence_service.py @@ -216,11 +216,12 @@ class RecipePersistenceService: "preview_nsfw_level", "favorite", "gen_params", + "base_model", ) if not any(key in updates for key in allowed_fields): raise RecipeValidationError( - "At least one field to update must be provided (title or tags or source_path or preview_nsfw_level or favorite or gen_params)" + "At least one field to update must be provided (title or tags or source_path or preview_nsfw_level or favorite or gen_params or base_model)" ) if "gen_params" in updates and not isinstance(updates["gen_params"], dict): diff --git a/static/js/managers/BulkManager.js b/static/js/managers/BulkManager.js index f1b7c01a..a0917acb 100644 --- a/static/js/managers/BulkManager.js +++ b/static/js/managers/BulkManager.js @@ -1665,13 +1665,19 @@ export class BulkManager { cancelled = true; }); + const isRecipesPage = state.currentPageType === 'recipes'; + for (const filepath of state.selectedModels) { if (cancelled) { showToast('toast.api.operationCancelled', {}, 'info'); break; } try { - await getModelApiClient().saveModelMetadata(filepath, { base_model: newBaseModel }); + if (isRecipesPage) { + await updateRecipeMetadata(filepath, { base_model: newBaseModel }); + } else { + await getModelApiClient().saveModelMetadata(filepath, { base_model: newBaseModel }); + } successCount++; } catch (error) { errorCount++;