73 lines
3.2 KiB
Python
73 lines
3.2 KiB
Python
""" Utility functions related to django storages """
|
|
import logging
|
|
|
|
from typing import Optional, List
|
|
from django.conf import settings
|
|
from django.core.files.storage import storages
|
|
from django.utils.module_loading import import_string
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def resolve_storage_backend(
|
|
storage_key: str,
|
|
legacy_setting_key: str,
|
|
legacy_sec_setting_keys: List[str] = None,
|
|
options: Optional[dict] = None):
|
|
"""
|
|
Configures and returns a Django `Storage` instance, compatible with both Django 4 and Django 5.
|
|
Params:
|
|
storage_key = The key name saved in Django storages settings.
|
|
legacy_setting_key = The key name saved in Django settings.
|
|
legacy_sec_setting_keys = List of keys to get the storage class.
|
|
For legacy dict settings like settings.BLOCK_STRUCTURES_SETTINGS.get('STORAGE_CLASS'),
|
|
it is necessary to access a second-level key or above to retrieve the class path.
|
|
options = Kwargs for the storage class.
|
|
Returns:
|
|
An instance of the configured storage backend.
|
|
Raises:
|
|
ImportError: If the specified storage class cannot be imported.
|
|
KeyError: If the specified key is not found in the legacy settings.
|
|
Main goal:
|
|
Deprecate the use of `django.core.files.storage.get_storage_class`.
|
|
How:
|
|
Replace `get_storage_class` with direct configuration logic,
|
|
ensuring backward compatibility with both Django 4 and Django 5 storage settings.
|
|
"""
|
|
|
|
storage_path = getattr(settings, legacy_setting_key, None)
|
|
storages_config = getattr(settings, 'STORAGES', {})
|
|
options = options or {}
|
|
|
|
if storage_key in storages_config:
|
|
# Use case 1: STORAGES is defined
|
|
# If STORAGES is present, we retrieve it through the storages API
|
|
# settings.py must define STORAGES like:
|
|
# STORAGES = {
|
|
# "default": {"BACKEND": "...", "OPTIONS": {...}},
|
|
# "custom": {"BACKEND": "...", "OPTIONS": {...}},
|
|
# }
|
|
# See: https://docs.djangoproject.com/en/5.2/ref/settings/#std-setting-STORAGES
|
|
return storages[storage_key]
|
|
|
|
# Use case 2: Legacy settings
|
|
# Fallback to import the storage_path (Obtained from django settings) manually
|
|
if isinstance(storage_path, dict) and legacy_sec_setting_keys:
|
|
# If storage_path is a dict, we need to access the second-level keys
|
|
# to retrieve the storage class path.
|
|
# This is useful for legacy settings that store storage paths in a nested structure.
|
|
for deep_setting_key in legacy_sec_setting_keys:
|
|
# For legacy dict settings like settings.CUSTOM_STORAGE = {"BACKEND": "cms.custom.."}
|
|
if deep_setting_key not in storage_path:
|
|
logger.warning(
|
|
f"Key {legacy_setting_key} '{deep_setting_key}' not found in storage settings {storage_path}."
|
|
"Using default storage path."
|
|
)
|
|
storage_path = None # We set it to None to use the default storage later
|
|
break
|
|
storage_path = storage_path.get(deep_setting_key)
|
|
|
|
StorageClass = import_string(storage_path or storages_config["default"]["BACKEND"])
|
|
return StorageClass(**options)
|