mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-25 07:05:43 -03:00
feat: update download path template handling for model types and migrate old settings
This commit is contained in:
@@ -756,8 +756,8 @@ class BaseModelRoutes(ABC):
|
|||||||
'error': 'No model roots configured'
|
'error': 'No model roots configured'
|
||||||
}, status=400)
|
}, status=400)
|
||||||
|
|
||||||
# Check if flat structure is configured
|
# Check if flat structure is configured for this model type
|
||||||
path_template = settings.get('download_path_template', '{base_model}/{first_tag}')
|
path_template = settings.get_download_path_template(self.service.model_type)
|
||||||
is_flat_structure = not path_template
|
is_flat_structure = not path_template
|
||||||
|
|
||||||
# Prepare results tracking
|
# Prepare results tracking
|
||||||
@@ -832,7 +832,7 @@ class BaseModelRoutes(ABC):
|
|||||||
target_dir = current_root
|
target_dir = current_root
|
||||||
else:
|
else:
|
||||||
# Calculate new relative path based on settings
|
# Calculate new relative path based on settings
|
||||||
new_relative_path = calculate_relative_path_for_model(model)
|
new_relative_path = calculate_relative_path_for_model(model, self.service.model_type)
|
||||||
|
|
||||||
# If no relative path calculated (insufficient metadata), skip
|
# If no relative path calculated (insufficient metadata), skip
|
||||||
if not new_relative_path:
|
if not new_relative_path:
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ class DownloadManager:
|
|||||||
save_dir = default_path
|
save_dir = default_path
|
||||||
|
|
||||||
# Calculate relative path using template
|
# Calculate relative path using template
|
||||||
relative_path = self._calculate_relative_path(version_info)
|
relative_path = self._calculate_relative_path(version_info, model_type)
|
||||||
|
|
||||||
# Update save directory with relative path if provided
|
# Update save directory with relative path if provided
|
||||||
if relative_path:
|
if relative_path:
|
||||||
@@ -331,17 +331,18 @@ class DownloadManager:
|
|||||||
return {'success': False, 'error': f"Early access restriction: {str(e)}. Please ensure you have purchased early access and are logged in to Civitai."}
|
return {'success': False, 'error': f"Early access restriction: {str(e)}. Please ensure you have purchased early access and are logged in to Civitai."}
|
||||||
return {'success': False, 'error': str(e)}
|
return {'success': False, 'error': str(e)}
|
||||||
|
|
||||||
def _calculate_relative_path(self, version_info: Dict) -> str:
|
def _calculate_relative_path(self, version_info: Dict, model_type: str = 'lora') -> str:
|
||||||
"""Calculate relative path using template from settings
|
"""Calculate relative path using template from settings
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
version_info: Version info from Civitai API
|
version_info: Version info from Civitai API
|
||||||
|
model_type: Type of model ('lora', 'checkpoint', 'embedding')
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Relative path string
|
Relative path string
|
||||||
"""
|
"""
|
||||||
# Get path template from settings, default to '{base_model}/{first_tag}'
|
# Get path template from settings for specific model type
|
||||||
path_template = settings.get('download_path_template', '{base_model}/{first_tag}')
|
path_template = settings.get_download_path_template(model_type)
|
||||||
|
|
||||||
# If template is empty, return empty path (flat structure)
|
# If template is empty, return empty path (flat structure)
|
||||||
if not path_template:
|
if not path_template:
|
||||||
@@ -350,6 +351,9 @@ class DownloadManager:
|
|||||||
# Get base model name
|
# Get base model name
|
||||||
base_model = version_info.get('baseModel', '')
|
base_model = version_info.get('baseModel', '')
|
||||||
|
|
||||||
|
# Get author from creator data
|
||||||
|
author = version_info.get('creator', {}).get('username', 'Anonymous')
|
||||||
|
|
||||||
# Apply mapping if available
|
# Apply mapping if available
|
||||||
base_model_mappings = settings.get('base_model_path_mappings', {})
|
base_model_mappings = settings.get('base_model_path_mappings', {})
|
||||||
mapped_base_model = base_model_mappings.get(base_model, base_model)
|
mapped_base_model = base_model_mappings.get(base_model, base_model)
|
||||||
@@ -372,6 +376,7 @@ class DownloadManager:
|
|||||||
formatted_path = path_template
|
formatted_path = path_template
|
||||||
formatted_path = formatted_path.replace('{base_model}', mapped_base_model)
|
formatted_path = formatted_path.replace('{base_model}', mapped_base_model)
|
||||||
formatted_path = formatted_path.replace('{first_tag}', first_tag)
|
formatted_path = formatted_path.replace('{first_tag}', first_tag)
|
||||||
|
formatted_path = formatted_path.replace('{author}', author)
|
||||||
|
|
||||||
return formatted_path
|
return formatted_path
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ class SettingsManager:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.settings_file = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'settings.json')
|
self.settings_file = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'settings.json')
|
||||||
self.settings = self._load_settings()
|
self.settings = self._load_settings()
|
||||||
|
self._migrate_download_path_template()
|
||||||
self._auto_set_default_roots()
|
self._auto_set_default_roots()
|
||||||
self._check_environment_variables()
|
self._check_environment_variables()
|
||||||
|
|
||||||
@@ -22,6 +23,24 @@ class SettingsManager:
|
|||||||
logger.error(f"Error loading settings: {e}")
|
logger.error(f"Error loading settings: {e}")
|
||||||
return self._get_default_settings()
|
return self._get_default_settings()
|
||||||
|
|
||||||
|
def _migrate_download_path_template(self):
|
||||||
|
"""Migrate old download_path_template to new download_path_templates"""
|
||||||
|
old_template = self.settings.get('download_path_template')
|
||||||
|
templates = self.settings.get('download_path_templates')
|
||||||
|
|
||||||
|
# If old template exists and new templates don't exist, migrate
|
||||||
|
if old_template is not None and not templates:
|
||||||
|
logger.info("Migrating download_path_template to download_path_templates")
|
||||||
|
self.settings['download_path_templates'] = {
|
||||||
|
'lora': old_template,
|
||||||
|
'checkpoint': old_template,
|
||||||
|
'embedding': old_template
|
||||||
|
}
|
||||||
|
# Remove old setting
|
||||||
|
del self.settings['download_path_template']
|
||||||
|
self._save_settings()
|
||||||
|
logger.info("Migration completed")
|
||||||
|
|
||||||
def _auto_set_default_roots(self):
|
def _auto_set_default_roots(self):
|
||||||
"""Auto set default root paths if only one folder is present and default is empty."""
|
"""Auto set default root paths if only one folder is present and default is empty."""
|
||||||
folder_paths = self.settings.get('folder_paths', {})
|
folder_paths = self.settings.get('folder_paths', {})
|
||||||
@@ -81,4 +100,16 @@ class SettingsManager:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Error saving settings: {e}")
|
logger.error(f"Error saving settings: {e}")
|
||||||
|
|
||||||
|
def get_download_path_template(self, model_type: str) -> str:
|
||||||
|
"""Get download path template for specific model type
|
||||||
|
|
||||||
|
Args:
|
||||||
|
model_type: The type of model ('lora', 'checkpoint', 'embedding')
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Template string for the model type, defaults to '{base_model}/{first_tag}'
|
||||||
|
"""
|
||||||
|
templates = self.settings.get('download_path_templates', {})
|
||||||
|
return templates.get(model_type, '{base_model}/{first_tag}')
|
||||||
|
|
||||||
settings = SettingsManager()
|
settings = SettingsManager()
|
||||||
|
|||||||
@@ -132,17 +132,18 @@ def calculate_recipe_fingerprint(loras):
|
|||||||
|
|
||||||
return fingerprint
|
return fingerprint
|
||||||
|
|
||||||
def calculate_relative_path_for_model(model_data: Dict) -> str:
|
def calculate_relative_path_for_model(model_data: Dict, model_type: str = 'lora') -> str:
|
||||||
"""Calculate relative path for existing model using template from settings
|
"""Calculate relative path for existing model using template from settings
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
model_data: Model data from scanner cache
|
model_data: Model data from scanner cache
|
||||||
|
model_type: Type of model ('lora', 'checkpoint', 'embedding')
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
Relative path string (empty string for flat structure)
|
Relative path string (empty string for flat structure)
|
||||||
"""
|
"""
|
||||||
# Get path template from settings, default to '{base_model}/{first_tag}'
|
# Get path template from settings for specific model type
|
||||||
path_template = settings.get('download_path_template', '{base_model}/{first_tag}')
|
path_template = settings.get_download_path_template(model_type)
|
||||||
|
|
||||||
# If template is empty, return empty path (flat structure)
|
# If template is empty, return empty path (flat structure)
|
||||||
if not path_template:
|
if not path_template:
|
||||||
@@ -154,9 +155,12 @@ def calculate_relative_path_for_model(model_data: Dict) -> str:
|
|||||||
# For CivitAI models, prefer civitai data only if 'id' exists; for non-CivitAI models, use model_data directly
|
# For CivitAI models, prefer civitai data only if 'id' exists; for non-CivitAI models, use model_data directly
|
||||||
if civitai_data and civitai_data.get('id') is not None:
|
if civitai_data and civitai_data.get('id') is not None:
|
||||||
base_model = civitai_data.get('baseModel', '')
|
base_model = civitai_data.get('baseModel', '')
|
||||||
|
# Get author from civitai creator data
|
||||||
|
author = civitai_data.get('creator', {}).get('username', 'Anonymous')
|
||||||
else:
|
else:
|
||||||
# Fallback to model_data fields for non-CivitAI models
|
# Fallback to model_data fields for non-CivitAI models
|
||||||
base_model = model_data.get('base_model', '')
|
base_model = model_data.get('base_model', '')
|
||||||
|
author = 'Anonymous' # Default for non-CivitAI models
|
||||||
|
|
||||||
model_tags = model_data.get('tags', [])
|
model_tags = model_data.get('tags', [])
|
||||||
|
|
||||||
@@ -182,6 +186,7 @@ def calculate_relative_path_for_model(model_data: Dict) -> str:
|
|||||||
formatted_path = path_template
|
formatted_path = path_template
|
||||||
formatted_path = formatted_path.replace('{base_model}', mapped_base_model)
|
formatted_path = formatted_path.replace('{base_model}', mapped_base_model)
|
||||||
formatted_path = formatted_path.replace('{first_tag}', first_tag)
|
formatted_path = formatted_path.replace('{first_tag}', first_tag)
|
||||||
|
formatted_path = formatted_path.replace('{author}', author)
|
||||||
|
|
||||||
return formatted_path
|
return formatted_path
|
||||||
|
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ export class SettingsManager {
|
|||||||
|
|
||||||
// Ensure all model types have templates
|
// Ensure all model types have templates
|
||||||
Object.keys(DEFAULT_PATH_TEMPLATES).forEach(modelType => {
|
Object.keys(DEFAULT_PATH_TEMPLATES).forEach(modelType => {
|
||||||
if (!state.global.settings.download_path_templates[modelType]) {
|
if (typeof state.global.settings.download_path_templates[modelType] === 'undefined') {
|
||||||
state.global.settings.download_path_templates[modelType] = DEFAULT_PATH_TEMPLATES[modelType];
|
state.global.settings.download_path_templates[modelType] = DEFAULT_PATH_TEMPLATES[modelType];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -586,7 +586,7 @@ export class SettingsManager {
|
|||||||
// Find matching preset
|
// Find matching preset
|
||||||
const matchingPreset = this.findMatchingPreset(template);
|
const matchingPreset = this.findMatchingPreset(template);
|
||||||
|
|
||||||
if (matchingPreset) {
|
if (matchingPreset !== null) {
|
||||||
presetSelect.value = matchingPreset;
|
presetSelect.value = matchingPreset;
|
||||||
if (customRow) customRow.style.display = 'none';
|
if (customRow) customRow.style.display = 'none';
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user