1
0
mirror of https://github.com/django/django.git synced 2025-10-31 01:25:32 +00:00

Fixed #26029 -- Allowed configuring custom file storage backends.

This commit is contained in:
Jarosław Wygoda
2023-01-11 10:48:57 +01:00
committed by Mariusz Felisiak
parent d02a9f0cee
commit 1ec3f0961f
12 changed files with 209 additions and 11 deletions

View File

@@ -280,6 +280,8 @@ SECRET_KEY_FALLBACKS = []
# Default file storage mechanism that holds media.
DEFAULT_FILE_STORAGE = "django.core.files.storage.FileSystemStorage"
STORAGES = {}
# Absolute filesystem path to the directory that will hold user-uploaded files.
# Example: "/var/www/example.com/media/"
MEDIA_ROOT = ""

View File

@@ -4,6 +4,7 @@ from django.utils.module_loading import import_string
from .base import Storage
from .filesystem import FileSystemStorage
from .handler import InvalidStorageError, StorageHandler
from .memory import InMemoryStorage
__all__ = (
@@ -13,6 +14,9 @@ __all__ = (
"DefaultStorage",
"default_storage",
"get_storage_class",
"InvalidStorageError",
"StorageHandler",
"storages",
)
@@ -25,4 +29,5 @@ class DefaultStorage(LazyObject):
self._wrapped = get_storage_class()()
storages = StorageHandler()
default_storage = DefaultStorage()

View File

@@ -0,0 +1,46 @@
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.utils.functional import cached_property
from django.utils.module_loading import import_string
class InvalidStorageError(ImproperlyConfigured):
pass
class StorageHandler:
def __init__(self, backends=None):
# backends is an optional dict of storage backend definitions
# (structured like settings.STORAGES).
self._backends = backends
self._storages = {}
@cached_property
def backends(self):
if self._backends is None:
self._backends = settings.STORAGES.copy()
return self._backends
def __getitem__(self, alias):
try:
return self._storages[alias]
except KeyError:
try:
params = self.backends[alias]
except KeyError:
raise InvalidStorageError(
f"Could not find config for '{alias}' in settings.STORAGES."
)
storage = self.create_storage(params)
self._storages[alias] = storage
return storage
def create_storage(self, params):
params = params.copy()
backend = params.pop("BACKEND")
options = params.pop("OPTIONS", {})
try:
storage_cls = import_string(backend)
except ImportError as e:
raise InvalidStorageError(f"Could not find backend {backend!r}: {e}") from e
return storage_cls(**options)

View File

@@ -111,6 +111,23 @@ def reset_template_engines(*, setting, **kwargs):
get_default_renderer.cache_clear()
@receiver(setting_changed)
def storages_changed(*, setting, **kwargs):
from django.core.files.storage import storages
if setting in (
"STORAGES",
"STATIC_ROOT",
"STATIC_URL",
):
try:
del storages.backends
except AttributeError:
pass
storages._backends = None
storages._storages = {}
@receiver(setting_changed)
def clear_serializers_cache(*, setting, **kwargs):
if setting == "SERIALIZATION_MODULES":