mirror of
https://github.com/django/django.git
synced 2025-08-11 12:29:12 +00:00
Refs #26029 -- Deprecated DEFAULT_FILE_STORAGE and STATICFILES_STORAGE settings.
This commit is contained in:
parent
1ec3f0961f
commit
32940d390a
@ -16,10 +16,12 @@ from pathlib import Path
|
|||||||
import django
|
import django
|
||||||
from django.conf import global_settings
|
from django.conf import global_settings
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.utils.deprecation import RemovedInDjango50Warning
|
from django.utils.deprecation import RemovedInDjango50Warning, RemovedInDjango51Warning
|
||||||
from django.utils.functional import LazyObject, empty
|
from django.utils.functional import LazyObject, empty
|
||||||
|
|
||||||
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
|
ENVIRONMENT_VARIABLE = "DJANGO_SETTINGS_MODULE"
|
||||||
|
DEFAULT_STORAGE_ALIAS = "default"
|
||||||
|
STATICFILES_STORAGE_ALIAS = "staticfiles"
|
||||||
|
|
||||||
# RemovedInDjango50Warning
|
# RemovedInDjango50Warning
|
||||||
USE_DEPRECATED_PYTZ_DEPRECATED_MSG = (
|
USE_DEPRECATED_PYTZ_DEPRECATED_MSG = (
|
||||||
@ -39,6 +41,14 @@ CSRF_COOKIE_MASKED_DEPRECATED_MSG = (
|
|||||||
"it will be removed in Django 5.0."
|
"it will be removed in Django 5.0."
|
||||||
)
|
)
|
||||||
|
|
||||||
|
DEFAULT_FILE_STORAGE_DEPRECATED_MSG = (
|
||||||
|
"The DEFAULT_FILE_STORAGE setting is deprecated. Use STORAGES instead."
|
||||||
|
)
|
||||||
|
|
||||||
|
STATICFILES_STORAGE_DEPRECATED_MSG = (
|
||||||
|
"The STATICFILES_STORAGE setting is deprecated. Use STORAGES instead."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SettingsReference(str):
|
class SettingsReference(str):
|
||||||
"""
|
"""
|
||||||
@ -177,6 +187,22 @@ class LazySettings(LazyObject):
|
|||||||
# paths.
|
# paths.
|
||||||
return self.__getattr__("USE_L10N")
|
return self.__getattr__("USE_L10N")
|
||||||
|
|
||||||
|
# RemovedInDjango51Warning.
|
||||||
|
@property
|
||||||
|
def DEFAULT_FILE_STORAGE(self):
|
||||||
|
self._show_deprecation_warning(
|
||||||
|
DEFAULT_FILE_STORAGE_DEPRECATED_MSG, RemovedInDjango51Warning
|
||||||
|
)
|
||||||
|
return self.__getattr__("DEFAULT_FILE_STORAGE")
|
||||||
|
|
||||||
|
# RemovedInDjango51Warning.
|
||||||
|
@property
|
||||||
|
def STATICFILES_STORAGE(self):
|
||||||
|
self._show_deprecation_warning(
|
||||||
|
STATICFILES_STORAGE_DEPRECATED_MSG, RemovedInDjango51Warning
|
||||||
|
)
|
||||||
|
return self.__getattr__("STATICFILES_STORAGE")
|
||||||
|
|
||||||
|
|
||||||
class Settings:
|
class Settings:
|
||||||
def __init__(self, settings_module):
|
def __init__(self, settings_module):
|
||||||
@ -240,6 +266,20 @@ class Settings:
|
|||||||
if self.is_overridden("USE_L10N"):
|
if self.is_overridden("USE_L10N"):
|
||||||
warnings.warn(USE_L10N_DEPRECATED_MSG, RemovedInDjango50Warning)
|
warnings.warn(USE_L10N_DEPRECATED_MSG, RemovedInDjango50Warning)
|
||||||
|
|
||||||
|
if self.is_overridden("DEFAULT_FILE_STORAGE"):
|
||||||
|
if self.is_overridden("STORAGES"):
|
||||||
|
raise ImproperlyConfigured(
|
||||||
|
"DEFAULT_FILE_STORAGE/STORAGES are mutually exclusive."
|
||||||
|
)
|
||||||
|
warnings.warn(DEFAULT_FILE_STORAGE_DEPRECATED_MSG, RemovedInDjango51Warning)
|
||||||
|
|
||||||
|
if self.is_overridden("STATICFILES_STORAGE"):
|
||||||
|
if self.is_overridden("STORAGES"):
|
||||||
|
raise ImproperlyConfigured(
|
||||||
|
"STATICFILES_STORAGE/STORAGES are mutually exclusive."
|
||||||
|
)
|
||||||
|
warnings.warn(STATICFILES_STORAGE_DEPRECATED_MSG, RemovedInDjango51Warning)
|
||||||
|
|
||||||
def is_overridden(self, setting):
|
def is_overridden(self, setting):
|
||||||
return setting in self._explicit_settings
|
return setting in self._explicit_settings
|
||||||
|
|
||||||
@ -276,9 +316,29 @@ class UserSettingsHolder:
|
|||||||
warnings.warn(USE_L10N_DEPRECATED_MSG, RemovedInDjango50Warning)
|
warnings.warn(USE_L10N_DEPRECATED_MSG, RemovedInDjango50Warning)
|
||||||
if name == "CSRF_COOKIE_MASKED":
|
if name == "CSRF_COOKIE_MASKED":
|
||||||
warnings.warn(CSRF_COOKIE_MASKED_DEPRECATED_MSG, RemovedInDjango50Warning)
|
warnings.warn(CSRF_COOKIE_MASKED_DEPRECATED_MSG, RemovedInDjango50Warning)
|
||||||
|
if name == "DEFAULT_FILE_STORAGE":
|
||||||
|
self.STORAGES[DEFAULT_STORAGE_ALIAS] = {
|
||||||
|
"BACKEND": self.DEFAULT_FILE_STORAGE
|
||||||
|
}
|
||||||
|
warnings.warn(DEFAULT_FILE_STORAGE_DEPRECATED_MSG, RemovedInDjango51Warning)
|
||||||
|
if name == "STATICFILES_STORAGE":
|
||||||
|
self.STORAGES[STATICFILES_STORAGE_ALIAS] = {
|
||||||
|
"BACKEND": self.STATICFILES_STORAGE
|
||||||
|
}
|
||||||
|
warnings.warn(STATICFILES_STORAGE_DEPRECATED_MSG, RemovedInDjango51Warning)
|
||||||
super().__setattr__(name, value)
|
super().__setattr__(name, value)
|
||||||
if name == "USE_DEPRECATED_PYTZ":
|
if name == "USE_DEPRECATED_PYTZ":
|
||||||
warnings.warn(USE_DEPRECATED_PYTZ_DEPRECATED_MSG, RemovedInDjango50Warning)
|
warnings.warn(USE_DEPRECATED_PYTZ_DEPRECATED_MSG, RemovedInDjango50Warning)
|
||||||
|
# RemovedInDjango51Warning.
|
||||||
|
if name == "STORAGES":
|
||||||
|
self.STORAGES.setdefault(
|
||||||
|
DEFAULT_STORAGE_ALIAS,
|
||||||
|
{"BACKEND": "django.core.files.storage.FileSystemStorage"},
|
||||||
|
)
|
||||||
|
self.STORAGES.setdefault(
|
||||||
|
STATICFILES_STORAGE_ALIAS,
|
||||||
|
{"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage"},
|
||||||
|
)
|
||||||
|
|
||||||
def __delattr__(self, name):
|
def __delattr__(self, name):
|
||||||
self._deleted.add(name)
|
self._deleted.add(name)
|
||||||
|
@ -280,7 +280,14 @@ SECRET_KEY_FALLBACKS = []
|
|||||||
# Default file storage mechanism that holds media.
|
# Default file storage mechanism that holds media.
|
||||||
DEFAULT_FILE_STORAGE = "django.core.files.storage.FileSystemStorage"
|
DEFAULT_FILE_STORAGE = "django.core.files.storage.FileSystemStorage"
|
||||||
|
|
||||||
STORAGES = {}
|
STORAGES = {
|
||||||
|
"default": {
|
||||||
|
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
||||||
|
},
|
||||||
|
"staticfiles": {
|
||||||
|
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
# Absolute filesystem path to the directory that will hold user-uploaded files.
|
# Absolute filesystem path to the directory that will hold user-uploaded files.
|
||||||
# Example: "/var/www/example.com/media/"
|
# Example: "/var/www/example.com/media/"
|
||||||
|
@ -4,11 +4,11 @@ import posixpath
|
|||||||
import re
|
import re
|
||||||
from urllib.parse import unquote, urldefrag, urlsplit, urlunsplit
|
from urllib.parse import unquote, urldefrag, urlsplit, urlunsplit
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import STATICFILES_STORAGE_ALIAS, settings
|
||||||
from django.contrib.staticfiles.utils import check_settings, matches_patterns
|
from django.contrib.staticfiles.utils import check_settings, matches_patterns
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.core.files.base import ContentFile
|
from django.core.files.base import ContentFile
|
||||||
from django.core.files.storage import FileSystemStorage, get_storage_class
|
from django.core.files.storage import FileSystemStorage, storages
|
||||||
from django.utils.crypto import md5
|
from django.utils.crypto import md5
|
||||||
from django.utils.functional import LazyObject
|
from django.utils.functional import LazyObject
|
||||||
|
|
||||||
@ -526,7 +526,7 @@ class ManifestStaticFilesStorage(ManifestFilesMixin, StaticFilesStorage):
|
|||||||
|
|
||||||
class ConfiguredStorage(LazyObject):
|
class ConfiguredStorage(LazyObject):
|
||||||
def _setup(self):
|
def _setup(self):
|
||||||
self._wrapped = get_storage_class(settings.STATICFILES_STORAGE)()
|
self._wrapped = storages[STATICFILES_STORAGE_ALIAS]
|
||||||
|
|
||||||
|
|
||||||
staticfiles_storage = ConfiguredStorage()
|
staticfiles_storage = ConfiguredStorage()
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
from django.conf import settings
|
import warnings
|
||||||
|
|
||||||
|
from django.conf import DEFAULT_STORAGE_ALIAS, settings
|
||||||
|
from django.utils.deprecation import RemovedInDjango51Warning
|
||||||
from django.utils.functional import LazyObject
|
from django.utils.functional import LazyObject
|
||||||
from django.utils.module_loading import import_string
|
from django.utils.module_loading import import_string
|
||||||
|
|
||||||
@ -19,14 +22,20 @@ __all__ = (
|
|||||||
"storages",
|
"storages",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
GET_STORAGE_CLASS_DEPRECATED_MSG = (
|
||||||
|
"django.core.files.storage.get_storage_class is deprecated in favor of "
|
||||||
|
"using django.core.files.storage.storages."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_storage_class(import_path=None):
|
def get_storage_class(import_path=None):
|
||||||
|
warnings.warn(GET_STORAGE_CLASS_DEPRECATED_MSG, RemovedInDjango51Warning)
|
||||||
return import_string(import_path or settings.DEFAULT_FILE_STORAGE)
|
return import_string(import_path or settings.DEFAULT_FILE_STORAGE)
|
||||||
|
|
||||||
|
|
||||||
class DefaultStorage(LazyObject):
|
class DefaultStorage(LazyObject):
|
||||||
def _setup(self):
|
def _setup(self):
|
||||||
self._wrapped = get_storage_class()()
|
self._wrapped = storages[DEFAULT_STORAGE_ALIAS]
|
||||||
|
|
||||||
|
|
||||||
storages = StorageHandler()
|
storages = StorageHandler()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from django.conf import settings
|
from django.conf import DEFAULT_STORAGE_ALIAS, STATICFILES_STORAGE_ALIAS, settings
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.utils.functional import cached_property
|
from django.utils.functional import cached_property
|
||||||
from django.utils.module_loading import import_string
|
from django.utils.module_loading import import_string
|
||||||
@ -19,6 +19,15 @@ class StorageHandler:
|
|||||||
def backends(self):
|
def backends(self):
|
||||||
if self._backends is None:
|
if self._backends is None:
|
||||||
self._backends = settings.STORAGES.copy()
|
self._backends = settings.STORAGES.copy()
|
||||||
|
# RemovedInDjango51Warning.
|
||||||
|
if settings.is_overridden("DEFAULT_FILE_STORAGE"):
|
||||||
|
self._backends[DEFAULT_STORAGE_ALIAS] = {
|
||||||
|
"BACKEND": settings.DEFAULT_FILE_STORAGE
|
||||||
|
}
|
||||||
|
if settings.is_overridden("STATICFILES_STORAGE"):
|
||||||
|
self._backends[STATICFILES_STORAGE_ALIAS] = {
|
||||||
|
"BACKEND": settings.STATICFILES_STORAGE
|
||||||
|
}
|
||||||
return self._backends
|
return self._backends
|
||||||
|
|
||||||
def __getitem__(self, alias):
|
def __getitem__(self, alias):
|
||||||
|
@ -13,6 +13,7 @@ from django.dispatch import Signal, receiver
|
|||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.formats import FORMAT_SETTINGS, reset_format_cache
|
from django.utils.formats import FORMAT_SETTINGS, reset_format_cache
|
||||||
from django.utils.functional import empty
|
from django.utils.functional import empty
|
||||||
|
from django.utils.module_loading import import_string
|
||||||
|
|
||||||
template_rendered = Signal()
|
template_rendered = Signal()
|
||||||
|
|
||||||
@ -113,7 +114,8 @@ def reset_template_engines(*, setting, **kwargs):
|
|||||||
|
|
||||||
@receiver(setting_changed)
|
@receiver(setting_changed)
|
||||||
def storages_changed(*, setting, **kwargs):
|
def storages_changed(*, setting, **kwargs):
|
||||||
from django.core.files.storage import storages
|
from django.contrib.staticfiles.storage import staticfiles_storage
|
||||||
|
from django.core.files.storage import default_storage, storages
|
||||||
|
|
||||||
if setting in (
|
if setting in (
|
||||||
"STORAGES",
|
"STORAGES",
|
||||||
@ -127,6 +129,9 @@ def storages_changed(*, setting, **kwargs):
|
|||||||
storages._backends = None
|
storages._backends = None
|
||||||
storages._storages = {}
|
storages._storages = {}
|
||||||
|
|
||||||
|
default_storage._wrapped = empty
|
||||||
|
staticfiles_storage._wrapped = empty
|
||||||
|
|
||||||
|
|
||||||
@receiver(setting_changed)
|
@receiver(setting_changed)
|
||||||
def clear_serializers_cache(*, setting, **kwargs):
|
def clear_serializers_cache(*, setting, **kwargs):
|
||||||
@ -156,11 +161,18 @@ def localize_settings_changed(*, setting, **kwargs):
|
|||||||
reset_format_cache()
|
reset_format_cache()
|
||||||
|
|
||||||
|
|
||||||
|
# RemovedInDjango51Warning.
|
||||||
@receiver(setting_changed)
|
@receiver(setting_changed)
|
||||||
def file_storage_changed(*, setting, **kwargs):
|
def file_storage_changed(*, setting, **kwargs):
|
||||||
if setting == "DEFAULT_FILE_STORAGE":
|
if setting == "DEFAULT_FILE_STORAGE":
|
||||||
from django.core.files.storage import default_storage
|
from django.conf import DEFAULT_STORAGE_ALIAS
|
||||||
|
from django.core.files.storage import default_storage, storages
|
||||||
|
|
||||||
|
try:
|
||||||
|
del storages.backends
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
storages._storages[DEFAULT_STORAGE_ALIAS] = import_string(kwargs["value"])()
|
||||||
default_storage._wrapped = empty
|
default_storage._wrapped = empty
|
||||||
|
|
||||||
|
|
||||||
@ -195,6 +207,17 @@ def static_storage_changed(*, setting, **kwargs):
|
|||||||
|
|
||||||
staticfiles_storage._wrapped = empty
|
staticfiles_storage._wrapped = empty
|
||||||
|
|
||||||
|
# RemovedInDjango51Warning.
|
||||||
|
if setting == "STATICFILES_STORAGE":
|
||||||
|
from django.conf import STATICFILES_STORAGE_ALIAS
|
||||||
|
from django.core.files.storage import storages
|
||||||
|
|
||||||
|
try:
|
||||||
|
del storages.backends
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
storages._storages[STATICFILES_STORAGE_ALIAS] = import_string(kwargs["value"])()
|
||||||
|
|
||||||
|
|
||||||
@receiver(setting_changed)
|
@receiver(setting_changed)
|
||||||
def static_finders_changed(*, setting, **kwargs):
|
def static_finders_changed(*, setting, **kwargs):
|
||||||
|
@ -15,8 +15,8 @@ Serving static files in production
|
|||||||
The basic outline of putting static files into production consists of two
|
The basic outline of putting static files into production consists of two
|
||||||
steps: run the :djadmin:`collectstatic` command when static files change, then
|
steps: run the :djadmin:`collectstatic` command when static files change, then
|
||||||
arrange for the collected static files directory (:setting:`STATIC_ROOT`) to be
|
arrange for the collected static files directory (:setting:`STATIC_ROOT`) to be
|
||||||
moved to the static file server and served. Depending on
|
moved to the static file server and served. Depending the ``staticfiles``
|
||||||
:setting:`STATICFILES_STORAGE`, files may need to be moved to a new location
|
:setting:`STORAGES` alias, files may need to be moved to a new location
|
||||||
manually or the :func:`post_process
|
manually or the :func:`post_process
|
||||||
<django.contrib.staticfiles.storage.StaticFilesStorage.post_process>` method of
|
<django.contrib.staticfiles.storage.StaticFilesStorage.post_process>` method of
|
||||||
the ``Storage`` class might take care of that.
|
the ``Storage`` class might take care of that.
|
||||||
@ -85,17 +85,20 @@ There's any number of ways you might do this, but if the provider has an API,
|
|||||||
you can use a :doc:`custom file storage backend </howto/custom-file-storage>`
|
you can use a :doc:`custom file storage backend </howto/custom-file-storage>`
|
||||||
to integrate the CDN with your Django project. If you've written or are using a
|
to integrate the CDN with your Django project. If you've written or are using a
|
||||||
3rd party custom storage backend, you can tell :djadmin:`collectstatic` to use
|
3rd party custom storage backend, you can tell :djadmin:`collectstatic` to use
|
||||||
it by setting :setting:`STATICFILES_STORAGE` to the storage engine.
|
it by setting ``staticfiles`` in :setting:`STORAGES`.
|
||||||
|
|
||||||
For example, if you've written an S3 storage backend in
|
For example, if you've written an S3 storage backend in
|
||||||
``myproject.storage.S3Storage`` you could use it with::
|
``myproject.storage.S3Storage`` you could use it with::
|
||||||
|
|
||||||
STATICFILES_STORAGE = 'myproject.storage.S3Storage'
|
STORAGES = {
|
||||||
|
# ...
|
||||||
|
"staticfiles": {"BACKEND": "myproject.storage.S3Storage"}
|
||||||
|
}
|
||||||
|
|
||||||
Once that's done, all you have to do is run :djadmin:`collectstatic` and your
|
Once that's done, all you have to do is run :djadmin:`collectstatic` and your
|
||||||
static files would be pushed through your storage package up to S3. If you
|
static files would be pushed through your storage package up to S3. If you
|
||||||
later needed to switch to a different storage provider, you may only have to
|
later needed to switch to a different storage provider, you may only have to
|
||||||
change your :setting:`STATICFILES_STORAGE` setting.
|
change ``staticfiles`` in the :setting:`STORAGES` setting.
|
||||||
|
|
||||||
For details on how you'd write one of these backends, see
|
For details on how you'd write one of these backends, see
|
||||||
:doc:`/howto/custom-file-storage`. There are 3rd party apps available that
|
:doc:`/howto/custom-file-storage`. There are 3rd party apps available that
|
||||||
@ -103,6 +106,10 @@ provide storage backends for many common file storage APIs. A good starting
|
|||||||
point is the `overview at djangopackages.org
|
point is the `overview at djangopackages.org
|
||||||
<https://djangopackages.org/grids/g/storage-backends/>`_.
|
<https://djangopackages.org/grids/g/storage-backends/>`_.
|
||||||
|
|
||||||
|
.. versionchanged:: 4.2
|
||||||
|
|
||||||
|
The :setting:`STORAGES` setting was added.
|
||||||
|
|
||||||
Learn more
|
Learn more
|
||||||
==========
|
==========
|
||||||
|
|
||||||
|
@ -19,7 +19,8 @@ Configuring static files
|
|||||||
STATIC_URL = 'static/'
|
STATIC_URL = 'static/'
|
||||||
|
|
||||||
#. In your templates, use the :ttag:`static` template tag to build the URL for
|
#. In your templates, use the :ttag:`static` template tag to build the URL for
|
||||||
the given relative path using the configured :setting:`STATICFILES_STORAGE`.
|
the given relative path using the configured ``staticfiles``
|
||||||
|
:setting:`STORAGES` alias.
|
||||||
|
|
||||||
.. _staticfiles-in-templates:
|
.. _staticfiles-in-templates:
|
||||||
|
|
||||||
|
@ -45,6 +45,12 @@ details on these changes.
|
|||||||
* Support for passing positional arguments to ``Signer`` and
|
* Support for passing positional arguments to ``Signer`` and
|
||||||
``TimestampSigner`` will be removed.
|
``TimestampSigner`` will be removed.
|
||||||
|
|
||||||
|
* The ``DEFAULT_FILE_STORAGE`` and ``STATICFILES_STORAGE`` settings will be
|
||||||
|
removed.
|
||||||
|
|
||||||
|
* The ``django.core.files.storage.get_storage_class()`` function will be
|
||||||
|
removed.
|
||||||
|
|
||||||
.. _deprecation-removed-in-5.0:
|
.. _deprecation-removed-in-5.0:
|
||||||
|
|
||||||
5.0
|
5.0
|
||||||
|
@ -60,11 +60,12 @@ specified by the :setting:`INSTALLED_APPS` setting.
|
|||||||
|
|
||||||
The :djadmin:`collectstatic` management command calls the
|
The :djadmin:`collectstatic` management command calls the
|
||||||
:meth:`~django.contrib.staticfiles.storage.StaticFilesStorage.post_process`
|
:meth:`~django.contrib.staticfiles.storage.StaticFilesStorage.post_process`
|
||||||
method of the :setting:`STATICFILES_STORAGE` after each run and passes
|
method of the ``staticfiles`` storage backend from :setting:`STORAGES` after
|
||||||
a list of paths that have been found by the management command. It also
|
each run and passes a list of paths that have been found by the management
|
||||||
receives all command line options of :djadmin:`collectstatic`. This is used
|
command. It also receives all command line options of :djadmin:`collectstatic`.
|
||||||
by the :class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage`
|
This is used by the
|
||||||
by default.
|
:class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage` by
|
||||||
|
default.
|
||||||
|
|
||||||
By default, collected files receive permissions from
|
By default, collected files receive permissions from
|
||||||
:setting:`FILE_UPLOAD_PERMISSIONS` and collected directories receive permissions
|
:setting:`FILE_UPLOAD_PERMISSIONS` and collected directories receive permissions
|
||||||
@ -82,7 +83,7 @@ respectively. For example::
|
|||||||
kwargs['directory_permissions_mode'] = 0o760
|
kwargs['directory_permissions_mode'] = 0o760
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
Then set the :setting:`STATICFILES_STORAGE` setting to
|
Then set the ``staticfiles`` storage backend in :setting:`STORAGES` setting to
|
||||||
``'path.to.MyStaticFilesStorage'``.
|
``'path.to.MyStaticFilesStorage'``.
|
||||||
|
|
||||||
Some commonly used options are:
|
Some commonly used options are:
|
||||||
@ -113,7 +114,8 @@ Some commonly used options are:
|
|||||||
|
|
||||||
Don't call the
|
Don't call the
|
||||||
:meth:`~django.contrib.staticfiles.storage.StaticFilesStorage.post_process`
|
:meth:`~django.contrib.staticfiles.storage.StaticFilesStorage.post_process`
|
||||||
method of the configured :setting:`STATICFILES_STORAGE` storage backend.
|
method of the configured ``staticfiles`` storage backend from
|
||||||
|
:setting:`STORAGES`.
|
||||||
|
|
||||||
.. django-admin-option:: --no-default-ignore
|
.. django-admin-option:: --no-default-ignore
|
||||||
|
|
||||||
@ -360,7 +362,7 @@ attribute. It defaults to 5.
|
|||||||
To enable the ``ManifestStaticFilesStorage`` you have to make sure the
|
To enable the ``ManifestStaticFilesStorage`` you have to make sure the
|
||||||
following requirements are met:
|
following requirements are met:
|
||||||
|
|
||||||
* the :setting:`STATICFILES_STORAGE` setting is set to
|
* the ``staticfiles`` storage backend in :setting:`STORAGES` setting is set to
|
||||||
``'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'``
|
``'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'``
|
||||||
* the :setting:`DEBUG` setting is set to ``False``
|
* the :setting:`DEBUG` setting is set to ``False``
|
||||||
* you've collected all your static files by using the
|
* you've collected all your static files by using the
|
||||||
@ -381,9 +383,9 @@ If a file isn't found in the ``staticfiles.json`` manifest at runtime, a
|
|||||||
|
|
||||||
Due to the requirement of running :djadmin:`collectstatic`, this storage
|
Due to the requirement of running :djadmin:`collectstatic`, this storage
|
||||||
typically shouldn't be used when running tests as ``collectstatic`` isn't run
|
typically shouldn't be used when running tests as ``collectstatic`` isn't run
|
||||||
as part of the normal test setup. During testing, ensure that the
|
as part of the normal test setup. During testing, ensure that ``staticfiles``
|
||||||
:setting:`STATICFILES_STORAGE` setting is set to something else like
|
storage backend in the :setting:`STORAGES` setting is set to something else
|
||||||
``'django.contrib.staticfiles.storage.StaticFilesStorage'`` (the default).
|
like ``'django.contrib.staticfiles.storage.StaticFilesStorage'`` (the default).
|
||||||
|
|
||||||
.. method:: storage.ManifestStaticFilesStorage.file_hash(name, content=None)
|
.. method:: storage.ManifestStaticFilesStorage.file_hash(name, content=None)
|
||||||
|
|
||||||
@ -434,7 +436,8 @@ files:
|
|||||||
- The builtin template tag :ttag:`static` which takes a path and urljoins it
|
- The builtin template tag :ttag:`static` which takes a path and urljoins it
|
||||||
with the static prefix :setting:`STATIC_URL`. If
|
with the static prefix :setting:`STATIC_URL`. If
|
||||||
``django.contrib.staticfiles`` is installed, the tag uses the ``url()``
|
``django.contrib.staticfiles`` is installed, the tag uses the ``url()``
|
||||||
method of the :setting:`STATICFILES_STORAGE` instead.
|
method of the ``staticfiles`` storage backend from :setting:`STORAGES`
|
||||||
|
instead.
|
||||||
|
|
||||||
- The builtin template tag :ttag:`get_static_prefix` which populates a
|
- The builtin template tag :ttag:`get_static_prefix` which populates a
|
||||||
template variable with the static prefix :setting:`STATIC_URL` to be
|
template variable with the static prefix :setting:`STATIC_URL` to be
|
||||||
@ -443,6 +446,9 @@ files:
|
|||||||
- The similar template tag :ttag:`get_media_prefix` which works like
|
- The similar template tag :ttag:`get_media_prefix` which works like
|
||||||
:ttag:`get_static_prefix` but uses :setting:`MEDIA_URL`.
|
:ttag:`get_static_prefix` but uses :setting:`MEDIA_URL`.
|
||||||
|
|
||||||
|
- The ``staticfiles`` key in :data:`django.core.files.storage.storages`
|
||||||
|
contains a ready-to-use instance of the staticfiles storage backend.
|
||||||
|
|
||||||
.. _staticfiles-development-view:
|
.. _staticfiles-development-view:
|
||||||
|
|
||||||
Static file development view
|
Static file development view
|
||||||
|
@ -18,9 +18,9 @@ Django provides convenient ways to access the default storage class:
|
|||||||
.. class:: DefaultStorage
|
.. class:: DefaultStorage
|
||||||
|
|
||||||
:class:`~django.core.files.storage.DefaultStorage` provides
|
:class:`~django.core.files.storage.DefaultStorage` provides
|
||||||
lazy access to the current default storage system as defined by
|
lazy access to the default storage system as defined by ``default`` key in
|
||||||
:setting:`DEFAULT_FILE_STORAGE`. :class:`DefaultStorage` uses
|
:setting:`STORAGES`. :class:`DefaultStorage` uses
|
||||||
:func:`~django.core.files.storage.get_storage_class` internally.
|
:data:`~django.core.files.storage.storages` internally.
|
||||||
|
|
||||||
.. data:: default_storage
|
.. data:: default_storage
|
||||||
|
|
||||||
@ -32,11 +32,16 @@ Django provides convenient ways to access the default storage class:
|
|||||||
Returns a class or module which implements the storage API.
|
Returns a class or module which implements the storage API.
|
||||||
|
|
||||||
When called without the ``import_path`` parameter ``get_storage_class``
|
When called without the ``import_path`` parameter ``get_storage_class``
|
||||||
will return the current default storage system as defined by
|
will return the default storage system as defined by ``default`` key in
|
||||||
:setting:`DEFAULT_FILE_STORAGE`. If ``import_path`` is provided,
|
:setting:`STORAGES`. If ``import_path`` is provided, ``get_storage_class``
|
||||||
``get_storage_class`` will attempt to import the class or module from the
|
will attempt to import the class or module from the given path and will
|
||||||
given path and will return it if successful. An exception will be
|
return it if successful. An exception will be raised if the import is
|
||||||
raised if the import is unsuccessful.
|
unsuccessful.
|
||||||
|
|
||||||
|
.. deprecated:: 4.2
|
||||||
|
|
||||||
|
The ``get_storage_class()`` function is deprecated. Use
|
||||||
|
:data:`storages` instead
|
||||||
|
|
||||||
The ``FileSystemStorage`` class
|
The ``FileSystemStorage`` class
|
||||||
===============================
|
===============================
|
||||||
|
@ -1356,6 +1356,12 @@ Default: ``'``:class:`django.core.files.storage.FileSystemStorage`\ ``'``
|
|||||||
Default file storage class to be used for any file-related operations that don't
|
Default file storage class to be used for any file-related operations that don't
|
||||||
specify a particular storage system. See :doc:`/topics/files`.
|
specify a particular storage system. See :doc:`/topics/files`.
|
||||||
|
|
||||||
|
.. deprecated:: 4.2
|
||||||
|
|
||||||
|
This setting is deprecated. Starting with Django 4.2, default file storage
|
||||||
|
engine can be configured with the :setting:`STORAGES` setting under the
|
||||||
|
``default`` key.
|
||||||
|
|
||||||
.. setting:: DEFAULT_FROM_EMAIL
|
.. setting:: DEFAULT_FROM_EMAIL
|
||||||
|
|
||||||
``DEFAULT_FROM_EMAIL``
|
``DEFAULT_FROM_EMAIL``
|
||||||
@ -2615,13 +2621,28 @@ See also the :doc:`/ref/checks` documentation.
|
|||||||
|
|
||||||
Default::
|
Default::
|
||||||
|
|
||||||
{}
|
{
|
||||||
|
"default": {
|
||||||
|
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
||||||
|
},
|
||||||
|
"staticfiles": {
|
||||||
|
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
A dictionary containing the settings for all storages to be used with Django.
|
A dictionary containing the settings for all storages to be used with Django.
|
||||||
It is a nested dictionary whose contents map a storage alias to a dictionary
|
It is a nested dictionary whose contents map a storage alias to a dictionary
|
||||||
containing the options for an individual storage.
|
containing the options for an individual storage.
|
||||||
|
|
||||||
Storages can have any alias you choose.
|
Storages can have any alias you choose. However, there are two aliases with
|
||||||
|
special significance:
|
||||||
|
|
||||||
|
* ``default`` for :doc:`managing files </topics/files>`.
|
||||||
|
``'``:class:`django.core.files.storage.FileSystemStorage`\ ``'`` is the
|
||||||
|
default storage engine.
|
||||||
|
* ``staticfiles`` for :doc:`managing static files </ref/contrib/staticfiles>`.
|
||||||
|
``'``:class:`django.contrib.staticfiles.storage.StaticFilesStorage`\ ``'`` is
|
||||||
|
the default storage engine.
|
||||||
|
|
||||||
The following is an example ``settings.py`` snippet defining a custom file
|
The following is an example ``settings.py`` snippet defining a custom file
|
||||||
storage called ``example``::
|
storage called ``example``::
|
||||||
@ -3598,10 +3619,16 @@ The file storage engine to use when collecting static files with the
|
|||||||
:djadmin:`collectstatic` management command.
|
:djadmin:`collectstatic` management command.
|
||||||
|
|
||||||
A ready-to-use instance of the storage backend defined in this setting
|
A ready-to-use instance of the storage backend defined in this setting
|
||||||
can be found at ``django.contrib.staticfiles.storage.staticfiles_storage``.
|
can be found under ``staticfiles`` key in ``django.core.files.storage.storages``.
|
||||||
|
|
||||||
For an example, see :ref:`staticfiles-from-cdn`.
|
For an example, see :ref:`staticfiles-from-cdn`.
|
||||||
|
|
||||||
|
.. deprecated:: 4.2
|
||||||
|
|
||||||
|
This setting is deprecated. Starting with Django 4.2, static files storage
|
||||||
|
engine can be configured with the :setting:`STORAGES` setting under the
|
||||||
|
``staticfiles`` key.
|
||||||
|
|
||||||
.. setting:: STATICFILES_FINDERS
|
.. setting:: STATICFILES_FINDERS
|
||||||
|
|
||||||
``STATICFILES_FINDERS``
|
``STATICFILES_FINDERS``
|
||||||
@ -3627,8 +3654,8 @@ used.
|
|||||||
One finder is disabled by default:
|
One finder is disabled by default:
|
||||||
``django.contrib.staticfiles.finders.DefaultStorageFinder``. If added to
|
``django.contrib.staticfiles.finders.DefaultStorageFinder``. If added to
|
||||||
your :setting:`STATICFILES_FINDERS` setting, it will look for static files in
|
your :setting:`STATICFILES_FINDERS` setting, it will look for static files in
|
||||||
the default file storage as defined by the :setting:`DEFAULT_FILE_STORAGE`
|
the default file storage as defined by the ``default`` key in the
|
||||||
setting.
|
:setting:`STORAGES` setting.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -2629,7 +2629,7 @@ A set of Django template filters useful for adding a "human touch" to data. See
|
|||||||
To link to static files that are saved in :setting:`STATIC_ROOT` Django ships
|
To link to static files that are saved in :setting:`STATIC_ROOT` Django ships
|
||||||
with a :ttag:`static` template tag. If the :mod:`django.contrib.staticfiles`
|
with a :ttag:`static` template tag. If the :mod:`django.contrib.staticfiles`
|
||||||
app is installed, the tag will serve files using ``url()`` method of the
|
app is installed, the tag will serve files using ``url()`` method of the
|
||||||
storage specified by :setting:`STATICFILES_STORAGE`. For example::
|
storage specified by ``staticfiles`` in :setting:`STORAGES`. For example::
|
||||||
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<img src="{% static 'images/hi.jpg' %}" alt="Hi!">
|
<img src="{% static 'images/hi.jpg' %}" alt="Hi!">
|
||||||
|
@ -95,7 +95,12 @@ Custom file storages
|
|||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
The new :setting:`STORAGES` setting allows configuring multiple custom file
|
The new :setting:`STORAGES` setting allows configuring multiple custom file
|
||||||
storage backends.
|
storage backends. It also controls storage engines for managing
|
||||||
|
:doc:`files </topics/files>` (the ``"defaut"`` key) and :doc:`static files
|
||||||
|
</ref/contrib/staticfiles>` (the ``"staticfiles"`` key).
|
||||||
|
|
||||||
|
The old ``DEFAULT_FILE_STORAGE`` and ``STATICFILES_STORAGE`` settings are
|
||||||
|
deprecated as of this release.
|
||||||
|
|
||||||
Minor features
|
Minor features
|
||||||
--------------
|
--------------
|
||||||
@ -674,3 +679,11 @@ Miscellaneous
|
|||||||
|
|
||||||
* Passing positional arguments to ``Signer`` and ``TimestampSigner`` is
|
* Passing positional arguments to ``Signer`` and ``TimestampSigner`` is
|
||||||
deprecated in favor of keyword-only arguments.
|
deprecated in favor of keyword-only arguments.
|
||||||
|
|
||||||
|
* The ``DEFAULT_FILE_STORAGE`` setting is deprecated in favor of
|
||||||
|
``STORAGES["default"]``.
|
||||||
|
|
||||||
|
* The ``STATICFILES_STORAGE`` setting is deprecated in favor of
|
||||||
|
``STORAGES["staticfiles"]``.
|
||||||
|
|
||||||
|
* The ``django.core.files.storage.get_storage_class()`` function is deprecated.
|
||||||
|
@ -156,9 +156,10 @@ Behind the scenes, Django delegates decisions about how and where to store files
|
|||||||
to a file storage system. This is the object that actually understands things
|
to a file storage system. This is the object that actually understands things
|
||||||
like file systems, opening and reading files, etc.
|
like file systems, opening and reading files, etc.
|
||||||
|
|
||||||
Django's default file storage is given by the :setting:`DEFAULT_FILE_STORAGE`
|
Django's default file storage is
|
||||||
setting; if you don't explicitly provide a storage system, this is the one that
|
``'``:class:`django.core.files.storage.FileSystemStorage`\ ``'``. If you don't
|
||||||
will be used.
|
explicitly provide a storage system in the ``default`` key of the
|
||||||
|
:setting:`STORAGES` setting, this is the one that will be used.
|
||||||
|
|
||||||
See below for details of the built-in default file storage system, and see
|
See below for details of the built-in default file storage system, and see
|
||||||
:doc:`/howto/custom-file-storage` for information on writing your own file
|
:doc:`/howto/custom-file-storage` for information on writing your own file
|
||||||
|
@ -1441,16 +1441,15 @@ when settings are changed.
|
|||||||
|
|
||||||
Django itself uses this signal to reset various data:
|
Django itself uses this signal to reset various data:
|
||||||
|
|
||||||
================================= ========================
|
============================================================================ ========================
|
||||||
Overridden settings Data reset
|
Overridden settings Data reset
|
||||||
================================= ========================
|
============================================================================ ========================
|
||||||
USE_TZ, TIME_ZONE Databases timezone
|
USE_TZ, TIME_ZONE Databases timezone
|
||||||
TEMPLATES Template engines
|
TEMPLATES Template engines
|
||||||
SERIALIZATION_MODULES Serializers cache
|
SERIALIZATION_MODULES Serializers cache
|
||||||
LOCALE_PATHS, LANGUAGE_CODE Default translation and loaded translations
|
LOCALE_PATHS, LANGUAGE_CODE Default translation and loaded translations
|
||||||
MEDIA_ROOT, DEFAULT_FILE_STORAGE Default file storage
|
DEFAULT_FILE_STORAGE, STATICFILES_STORAGE, STATIC_ROOT, STATIC_URL, STORAGES Storages configuration
|
||||||
STATIC_ROOT, STATIC_URL, STORAGES Storages configuration
|
============================================================================ ========================
|
||||||
================================= ========================
|
|
||||||
|
|
||||||
Isolating apps
|
Isolating apps
|
||||||
--------------
|
--------------
|
||||||
|
165
tests/deprecation/test_storages.py
Normal file
165
tests/deprecation/test_storages.py
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
import sys
|
||||||
|
from types import ModuleType
|
||||||
|
|
||||||
|
from django.conf import (
|
||||||
|
DEFAULT_FILE_STORAGE_DEPRECATED_MSG,
|
||||||
|
DEFAULT_STORAGE_ALIAS,
|
||||||
|
STATICFILES_STORAGE_ALIAS,
|
||||||
|
STATICFILES_STORAGE_DEPRECATED_MSG,
|
||||||
|
Settings,
|
||||||
|
settings,
|
||||||
|
)
|
||||||
|
from django.contrib.staticfiles.storage import (
|
||||||
|
ManifestStaticFilesStorage,
|
||||||
|
staticfiles_storage,
|
||||||
|
)
|
||||||
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
from django.core.files.storage import Storage, StorageHandler, default_storage, storages
|
||||||
|
from django.test import TestCase, ignore_warnings
|
||||||
|
from django.utils.deprecation import RemovedInDjango51Warning
|
||||||
|
|
||||||
|
|
||||||
|
class StaticfilesStorageDeprecationTests(TestCase):
|
||||||
|
msg = STATICFILES_STORAGE_DEPRECATED_MSG
|
||||||
|
|
||||||
|
def test_override_settings_warning(self):
|
||||||
|
with self.assertRaisesMessage(RemovedInDjango51Warning, self.msg):
|
||||||
|
with self.settings(
|
||||||
|
STATICFILES_STORAGE=(
|
||||||
|
"django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
|
||||||
|
)
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_settings_init(self):
|
||||||
|
settings_module = ModuleType("fake_settings_module")
|
||||||
|
settings_module.USE_TZ = True
|
||||||
|
settings_module.STATICFILES_STORAGE = (
|
||||||
|
"django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
|
||||||
|
)
|
||||||
|
sys.modules["fake_settings_module"] = settings_module
|
||||||
|
try:
|
||||||
|
with self.assertRaisesMessage(RemovedInDjango51Warning, self.msg):
|
||||||
|
Settings("fake_settings_module")
|
||||||
|
finally:
|
||||||
|
del sys.modules["fake_settings_module"]
|
||||||
|
|
||||||
|
def test_access_warning(self):
|
||||||
|
with self.assertRaisesMessage(RemovedInDjango51Warning, self.msg):
|
||||||
|
settings.STATICFILES_STORAGE
|
||||||
|
# Works a second time.
|
||||||
|
with self.assertRaisesMessage(RemovedInDjango51Warning, self.msg):
|
||||||
|
settings.STATICFILES_STORAGE
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango51Warning)
|
||||||
|
def test_access(self):
|
||||||
|
with self.settings(
|
||||||
|
STATICFILES_STORAGE=(
|
||||||
|
"django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
|
||||||
|
)
|
||||||
|
):
|
||||||
|
self.assertEqual(
|
||||||
|
settings.STATICFILES_STORAGE,
|
||||||
|
"django.contrib.staticfiles.storage.ManifestStaticFilesStorage",
|
||||||
|
)
|
||||||
|
# Works a second time.
|
||||||
|
self.assertEqual(
|
||||||
|
settings.STATICFILES_STORAGE,
|
||||||
|
"django.contrib.staticfiles.storage.ManifestStaticFilesStorage",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_use_both_error(self):
|
||||||
|
msg = "STATICFILES_STORAGE/STORAGES are mutually exclusive."
|
||||||
|
settings_module = ModuleType("fake_settings_module")
|
||||||
|
settings_module.USE_TZ = True
|
||||||
|
settings_module.STATICFILES_STORAGE = (
|
||||||
|
"django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
|
||||||
|
)
|
||||||
|
settings_module.STORAGES = {}
|
||||||
|
sys.modules["fake_settings_module"] = settings_module
|
||||||
|
try:
|
||||||
|
with self.assertRaisesMessage(ImproperlyConfigured, msg):
|
||||||
|
Settings("fake_settings_module")
|
||||||
|
finally:
|
||||||
|
del sys.modules["fake_settings_module"]
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango51Warning)
|
||||||
|
def test_storage(self):
|
||||||
|
empty_storages = StorageHandler()
|
||||||
|
with self.settings(
|
||||||
|
STATICFILES_STORAGE=(
|
||||||
|
"django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
|
||||||
|
)
|
||||||
|
):
|
||||||
|
self.assertIsInstance(
|
||||||
|
storages[STATICFILES_STORAGE_ALIAS],
|
||||||
|
ManifestStaticFilesStorage,
|
||||||
|
)
|
||||||
|
self.assertIsInstance(
|
||||||
|
empty_storages[STATICFILES_STORAGE_ALIAS],
|
||||||
|
ManifestStaticFilesStorage,
|
||||||
|
)
|
||||||
|
self.assertIsInstance(staticfiles_storage, ManifestStaticFilesStorage)
|
||||||
|
|
||||||
|
|
||||||
|
class DefaultStorageDeprecationTests(TestCase):
|
||||||
|
msg = DEFAULT_FILE_STORAGE_DEPRECATED_MSG
|
||||||
|
|
||||||
|
def test_override_settings_warning(self):
|
||||||
|
with self.assertRaisesMessage(RemovedInDjango51Warning, self.msg):
|
||||||
|
with self.settings(
|
||||||
|
DEFAULT_FILE_STORAGE=("django.core.files.storage.Storage")
|
||||||
|
):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_settings_init(self):
|
||||||
|
settings_module = ModuleType("fake_settings_module")
|
||||||
|
settings_module.USE_TZ = True
|
||||||
|
settings_module.DEFAULT_FILE_STORAGE = "django.core.files.storage.Storage"
|
||||||
|
sys.modules["fake_settings_module"] = settings_module
|
||||||
|
try:
|
||||||
|
with self.assertRaisesMessage(RemovedInDjango51Warning, self.msg):
|
||||||
|
Settings("fake_settings_module")
|
||||||
|
finally:
|
||||||
|
del sys.modules["fake_settings_module"]
|
||||||
|
|
||||||
|
def test_access_warning(self):
|
||||||
|
with self.assertRaisesMessage(RemovedInDjango51Warning, self.msg):
|
||||||
|
settings.DEFAULT_FILE_STORAGE
|
||||||
|
# Works a second time.
|
||||||
|
with self.assertRaisesMessage(RemovedInDjango51Warning, self.msg):
|
||||||
|
settings.DEFAULT_FILE_STORAGE
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango51Warning)
|
||||||
|
def test_access(self):
|
||||||
|
with self.settings(DEFAULT_FILE_STORAGE="django.core.files.storage.Storage"):
|
||||||
|
self.assertEqual(
|
||||||
|
settings.DEFAULT_FILE_STORAGE,
|
||||||
|
"django.core.files.storage.Storage",
|
||||||
|
)
|
||||||
|
# Works a second time.
|
||||||
|
self.assertEqual(
|
||||||
|
settings.DEFAULT_FILE_STORAGE,
|
||||||
|
"django.core.files.storage.Storage",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_use_both_error(self):
|
||||||
|
msg = "DEFAULT_FILE_STORAGE/STORAGES are mutually exclusive."
|
||||||
|
settings_module = ModuleType("fake_settings_module")
|
||||||
|
settings_module.USE_TZ = True
|
||||||
|
settings_module.DEFAULT_FILE_STORAGE = "django.core.files.storage.Storage"
|
||||||
|
settings_module.STORAGES = {}
|
||||||
|
sys.modules["fake_settings_module"] = settings_module
|
||||||
|
try:
|
||||||
|
with self.assertRaisesMessage(ImproperlyConfigured, msg):
|
||||||
|
Settings("fake_settings_module")
|
||||||
|
finally:
|
||||||
|
del sys.modules["fake_settings_module"]
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango51Warning)
|
||||||
|
def test_storage(self):
|
||||||
|
empty_storages = StorageHandler()
|
||||||
|
with self.settings(DEFAULT_FILE_STORAGE="django.core.files.storage.Storage"):
|
||||||
|
self.assertIsInstance(storages[DEFAULT_STORAGE_ALIAS], Storage)
|
||||||
|
self.assertIsInstance(empty_storages[DEFAULT_STORAGE_ALIAS], Storage)
|
||||||
|
self.assertIsInstance(default_storage, Storage)
|
@ -11,10 +11,15 @@ from io import StringIO
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from urllib.request import urlopen
|
from urllib.request import urlopen
|
||||||
|
|
||||||
|
from django.conf import DEFAULT_STORAGE_ALIAS, STATICFILES_STORAGE_ALIAS
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.core.exceptions import SuspiciousFileOperation
|
from django.core.exceptions import SuspiciousFileOperation
|
||||||
from django.core.files.base import ContentFile, File
|
from django.core.files.base import ContentFile, File
|
||||||
from django.core.files.storage import FileSystemStorage, InvalidStorageError
|
from django.core.files.storage import (
|
||||||
|
GET_STORAGE_CLASS_DEPRECATED_MSG,
|
||||||
|
FileSystemStorage,
|
||||||
|
InvalidStorageError,
|
||||||
|
)
|
||||||
from django.core.files.storage import Storage as BaseStorage
|
from django.core.files.storage import Storage as BaseStorage
|
||||||
from django.core.files.storage import (
|
from django.core.files.storage import (
|
||||||
StorageHandler,
|
StorageHandler,
|
||||||
@ -30,10 +35,11 @@ from django.core.files.uploadedfile import (
|
|||||||
from django.db.models import FileField
|
from django.db.models import FileField
|
||||||
from django.db.models.fields.files import FileDescriptor
|
from django.db.models.fields.files import FileDescriptor
|
||||||
from django.test import LiveServerTestCase, SimpleTestCase, TestCase, override_settings
|
from django.test import LiveServerTestCase, SimpleTestCase, TestCase, override_settings
|
||||||
from django.test.utils import requires_tz_support
|
from django.test.utils import ignore_warnings, requires_tz_support
|
||||||
from django.urls import NoReverseMatch, reverse_lazy
|
from django.urls import NoReverseMatch, reverse_lazy
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils._os import symlinks_supported
|
from django.utils._os import symlinks_supported
|
||||||
|
from django.utils.deprecation import RemovedInDjango51Warning
|
||||||
|
|
||||||
from .models import Storage, callable_storage, temp_storage, temp_storage_location
|
from .models import Storage, callable_storage, temp_storage, temp_storage_location
|
||||||
|
|
||||||
@ -41,6 +47,7 @@ FILE_SUFFIX_REGEX = "[A-Za-z0-9]{7}"
|
|||||||
|
|
||||||
|
|
||||||
class GetStorageClassTests(SimpleTestCase):
|
class GetStorageClassTests(SimpleTestCase):
|
||||||
|
@ignore_warnings(category=RemovedInDjango51Warning)
|
||||||
def test_get_filesystem_storage(self):
|
def test_get_filesystem_storage(self):
|
||||||
"""
|
"""
|
||||||
get_storage_class returns the class for a storage backend name/path.
|
get_storage_class returns the class for a storage backend name/path.
|
||||||
@ -50,6 +57,7 @@ class GetStorageClassTests(SimpleTestCase):
|
|||||||
FileSystemStorage,
|
FileSystemStorage,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango51Warning)
|
||||||
def test_get_invalid_storage_module(self):
|
def test_get_invalid_storage_module(self):
|
||||||
"""
|
"""
|
||||||
get_storage_class raises an error if the requested import don't exist.
|
get_storage_class raises an error if the requested import don't exist.
|
||||||
@ -57,6 +65,7 @@ class GetStorageClassTests(SimpleTestCase):
|
|||||||
with self.assertRaisesMessage(ImportError, "No module named 'storage'"):
|
with self.assertRaisesMessage(ImportError, "No module named 'storage'"):
|
||||||
get_storage_class("storage.NonexistentStorage")
|
get_storage_class("storage.NonexistentStorage")
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango51Warning)
|
||||||
def test_get_nonexistent_storage_class(self):
|
def test_get_nonexistent_storage_class(self):
|
||||||
"""
|
"""
|
||||||
get_storage_class raises an error if the requested class don't exist.
|
get_storage_class raises an error if the requested class don't exist.
|
||||||
@ -64,6 +73,7 @@ class GetStorageClassTests(SimpleTestCase):
|
|||||||
with self.assertRaises(ImportError):
|
with self.assertRaises(ImportError):
|
||||||
get_storage_class("django.core.files.storage.NonexistentStorage")
|
get_storage_class("django.core.files.storage.NonexistentStorage")
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango51Warning)
|
||||||
def test_get_nonexistent_storage_module(self):
|
def test_get_nonexistent_storage_module(self):
|
||||||
"""
|
"""
|
||||||
get_storage_class raises an error if the requested module don't exist.
|
get_storage_class raises an error if the requested module don't exist.
|
||||||
@ -75,6 +85,11 @@ class GetStorageClassTests(SimpleTestCase):
|
|||||||
"django.core.files.nonexistent_storage.NonexistentStorage"
|
"django.core.files.nonexistent_storage.NonexistentStorage"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_deprecation_warning(self):
|
||||||
|
msg = GET_STORAGE_CLASS_DEPRECATED_MSG
|
||||||
|
with self.assertRaisesMessage(RemovedInDjango51Warning, msg):
|
||||||
|
get_storage_class("django.core.files.storage.FileSystemStorage"),
|
||||||
|
|
||||||
|
|
||||||
class FileSystemStorageTests(unittest.TestCase):
|
class FileSystemStorageTests(unittest.TestCase):
|
||||||
def test_deconstruction(self):
|
def test_deconstruction(self):
|
||||||
@ -1179,7 +1194,17 @@ class StorageHandlerTests(SimpleTestCase):
|
|||||||
|
|
||||||
def test_defaults(self):
|
def test_defaults(self):
|
||||||
storages = StorageHandler()
|
storages = StorageHandler()
|
||||||
self.assertEqual(storages.backends, {})
|
self.assertEqual(
|
||||||
|
storages.backends,
|
||||||
|
{
|
||||||
|
DEFAULT_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
||||||
|
},
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": "django.contrib.staticfiles.storage.StaticFilesStorage",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
def test_nonexistent_alias(self):
|
def test_nonexistent_alias(self):
|
||||||
msg = "Could not find config for 'nonexistent' in settings.STORAGES."
|
msg = "Could not find config for 'nonexistent' in settings.STORAGES."
|
||||||
|
@ -9,6 +9,7 @@ from io import BytesIO, StringIO
|
|||||||
from unittest import mock
|
from unittest import mock
|
||||||
from urllib.parse import quote
|
from urllib.parse import quote
|
||||||
|
|
||||||
|
from django.conf import DEFAULT_STORAGE_ALIAS
|
||||||
from django.core.exceptions import SuspiciousFileOperation
|
from django.core.exceptions import SuspiciousFileOperation
|
||||||
from django.core.files import temp as tempfile
|
from django.core.files import temp as tempfile
|
||||||
from django.core.files.storage import default_storage
|
from django.core.files.storage import default_storage
|
||||||
@ -806,7 +807,11 @@ class DirectoryCreationTests(SimpleTestCase):
|
|||||||
sys.platform == "win32", "Python on Windows doesn't have working os.chmod()."
|
sys.platform == "win32", "Python on Windows doesn't have working os.chmod()."
|
||||||
)
|
)
|
||||||
@override_settings(
|
@override_settings(
|
||||||
DEFAULT_FILE_STORAGE="django.core.files.storage.FileSystemStorage"
|
STORAGES={
|
||||||
|
DEFAULT_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": "django.core.files.storage.FileSystemStorage",
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
def test_readonly_root(self):
|
def test_readonly_root(self):
|
||||||
"""Permission errors are not swallowed"""
|
"""Permission errors are not swallowed"""
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
from urllib.parse import urljoin
|
from urllib.parse import urljoin
|
||||||
|
|
||||||
|
from django.conf import STATICFILES_STORAGE_ALIAS
|
||||||
from django.contrib.staticfiles import storage
|
from django.contrib.staticfiles import storage
|
||||||
from django.forms import Media
|
from django.forms import Media
|
||||||
from django.templatetags.static import static
|
from django.templatetags.static import static
|
||||||
@ -12,9 +13,13 @@ class StaticTestStorage(storage.StaticFilesStorage):
|
|||||||
|
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
STATIC_URL="http://media.example.com/static/",
|
|
||||||
INSTALLED_APPS=("django.contrib.staticfiles",),
|
INSTALLED_APPS=("django.contrib.staticfiles",),
|
||||||
STATICFILES_STORAGE="staticfiles_tests.test_forms.StaticTestStorage",
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": "staticfiles_tests.test_forms.StaticTestStorage",
|
||||||
|
"OPTIONS": {"location": "http://media.example.com/static/"},
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
class StaticFilesFormsMediaTestCase(SimpleTestCase):
|
class StaticFilesFormsMediaTestCase(SimpleTestCase):
|
||||||
def test_absolute_url(self):
|
def test_absolute_url(self):
|
||||||
|
@ -9,7 +9,7 @@ from unittest import mock
|
|||||||
|
|
||||||
from admin_scripts.tests import AdminScriptTestCase
|
from admin_scripts.tests import AdminScriptTestCase
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import STATICFILES_STORAGE_ALIAS, settings
|
||||||
from django.contrib.staticfiles import storage
|
from django.contrib.staticfiles import storage
|
||||||
from django.contrib.staticfiles.management.commands import collectstatic, runserver
|
from django.contrib.staticfiles.management.commands import collectstatic, runserver
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
@ -141,16 +141,24 @@ class TestConfiguration(StaticFilesTestCase):
|
|||||||
try:
|
try:
|
||||||
storage.staticfiles_storage._wrapped = empty
|
storage.staticfiles_storage._wrapped = empty
|
||||||
with self.settings(
|
with self.settings(
|
||||||
STATICFILES_STORAGE=(
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": (
|
||||||
"django.contrib.staticfiles.storage.StaticFilesStorage"
|
"django.contrib.staticfiles.storage.StaticFilesStorage"
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
):
|
):
|
||||||
command = collectstatic.Command()
|
command = collectstatic.Command()
|
||||||
self.assertTrue(command.is_local_storage())
|
self.assertTrue(command.is_local_storage())
|
||||||
|
|
||||||
storage.staticfiles_storage._wrapped = empty
|
storage.staticfiles_storage._wrapped = empty
|
||||||
with self.settings(
|
with self.settings(
|
||||||
STATICFILES_STORAGE="staticfiles_tests.storage.DummyStorage"
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": "staticfiles_tests.storage.DummyStorage"
|
||||||
|
}
|
||||||
|
}
|
||||||
):
|
):
|
||||||
command = collectstatic.Command()
|
command = collectstatic.Command()
|
||||||
self.assertFalse(command.is_local_storage())
|
self.assertFalse(command.is_local_storage())
|
||||||
@ -241,9 +249,13 @@ class TestCollectionVerbosity(CollectionTestCase):
|
|||||||
self.assertIn(self.copying_msg, output)
|
self.assertIn(self.copying_msg, output)
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
STATICFILES_STORAGE=(
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": (
|
||||||
"django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
|
"django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
def test_verbosity_1_with_post_process(self):
|
def test_verbosity_1_with_post_process(self):
|
||||||
stdout = StringIO()
|
stdout = StringIO()
|
||||||
@ -251,9 +263,13 @@ class TestCollectionVerbosity(CollectionTestCase):
|
|||||||
self.assertNotIn(self.post_process_msg, stdout.getvalue())
|
self.assertNotIn(self.post_process_msg, stdout.getvalue())
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
STATICFILES_STORAGE=(
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": (
|
||||||
"django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
|
"django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
|
||||||
)
|
)
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
def test_verbosity_2_with_post_process(self):
|
def test_verbosity_2_with_post_process(self):
|
||||||
stdout = StringIO()
|
stdout = StringIO()
|
||||||
@ -280,7 +296,11 @@ class TestCollectionClear(CollectionTestCase):
|
|||||||
super().run_collectstatic(clear=True)
|
super().run_collectstatic(clear=True)
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
STATICFILES_STORAGE="staticfiles_tests.storage.PathNotImplementedStorage"
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": "staticfiles_tests.storage.PathNotImplementedStorage"
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
def test_handle_path_notimplemented(self):
|
def test_handle_path_notimplemented(self):
|
||||||
self.run_collectstatic()
|
self.run_collectstatic()
|
||||||
@ -395,7 +415,11 @@ class TestCollectionDryRun(TestNoFilesCreated, CollectionTestCase):
|
|||||||
|
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
STATICFILES_STORAGE="django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": "django.contrib.staticfiles.storage.ManifestStaticFilesStorage"
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
class TestCollectionDryRunManifestStaticFilesStorage(TestCollectionDryRun):
|
class TestCollectionDryRunManifestStaticFilesStorage(TestCollectionDryRun):
|
||||||
pass
|
pass
|
||||||
@ -518,7 +542,13 @@ class TestCollectionOverwriteWarning(CollectionTestCase):
|
|||||||
self.assertNotIn(self.warning_string, output)
|
self.assertNotIn(self.warning_string, output)
|
||||||
|
|
||||||
|
|
||||||
@override_settings(STATICFILES_STORAGE="staticfiles_tests.storage.DummyStorage")
|
@override_settings(
|
||||||
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": "staticfiles_tests.storage.DummyStorage"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
class TestCollectionNonLocalStorage(TestNoFilesCreated, CollectionTestCase):
|
class TestCollectionNonLocalStorage(TestNoFilesCreated, CollectionTestCase):
|
||||||
"""
|
"""
|
||||||
Tests for a Storage that implements get_modified_time() but not path()
|
Tests for a Storage that implements get_modified_time() but not path()
|
||||||
@ -540,7 +570,11 @@ class TestCollectionNonLocalStorage(TestNoFilesCreated, CollectionTestCase):
|
|||||||
|
|
||||||
class TestCollectionNeverCopyStorage(CollectionTestCase):
|
class TestCollectionNeverCopyStorage(CollectionTestCase):
|
||||||
@override_settings(
|
@override_settings(
|
||||||
STATICFILES_STORAGE="staticfiles_tests.storage.NeverCopyRemoteStorage"
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": "staticfiles_tests.storage.NeverCopyRemoteStorage"
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
def test_skips_newer_files_in_remote_storage(self):
|
def test_skips_newer_files_in_remote_storage(self):
|
||||||
"""
|
"""
|
||||||
@ -607,7 +641,11 @@ class TestCollectionLinks(TestDefaults, CollectionTestCase):
|
|||||||
self.assertFalse(os.path.lexists(broken_symlink_path))
|
self.assertFalse(os.path.lexists(broken_symlink_path))
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
STATICFILES_STORAGE="staticfiles_tests.storage.PathNotImplementedStorage"
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": "staticfiles_tests.storage.PathNotImplementedStorage"
|
||||||
|
}
|
||||||
|
}
|
||||||
)
|
)
|
||||||
def test_no_remote_link(self):
|
def test_no_remote_link(self):
|
||||||
with self.assertRaisesMessage(
|
with self.assertRaisesMessage(
|
||||||
|
@ -8,7 +8,7 @@ from io import StringIO
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import STATICFILES_STORAGE_ALIAS, settings
|
||||||
from django.contrib.staticfiles import finders, storage
|
from django.contrib.staticfiles import finders, storage
|
||||||
from django.contrib.staticfiles.management.commands.collectstatic import (
|
from django.contrib.staticfiles.management.commands.collectstatic import (
|
||||||
Command as CollectstaticCommand,
|
Command as CollectstaticCommand,
|
||||||
@ -369,7 +369,13 @@ class TestHashedFiles:
|
|||||||
self.assertPostCondition()
|
self.assertPostCondition()
|
||||||
|
|
||||||
|
|
||||||
@override_settings(STATICFILES_STORAGE="staticfiles_tests.storage.ExtraPatternsStorage")
|
@override_settings(
|
||||||
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": "staticfiles_tests.storage.ExtraPatternsStorage",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
class TestExtraPatternsStorage(CollectionTestCase):
|
class TestExtraPatternsStorage(CollectionTestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
storage.staticfiles_storage.hashed_files.clear() # avoid cache interference
|
storage.staticfiles_storage.hashed_files.clear() # avoid cache interference
|
||||||
@ -399,7 +405,11 @@ class TestExtraPatternsStorage(CollectionTestCase):
|
|||||||
|
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
STATICFILES_STORAGE="django.contrib.staticfiles.storage.ManifestStaticFilesStorage",
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": "django.contrib.staticfiles.storage.ManifestStaticFilesStorage",
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
class TestCollectionManifestStorage(TestHashedFiles, CollectionTestCase):
|
class TestCollectionManifestStorage(TestHashedFiles, CollectionTestCase):
|
||||||
"""
|
"""
|
||||||
@ -559,7 +569,13 @@ class TestCollectionManifestStorage(TestHashedFiles, CollectionTestCase):
|
|||||||
self.assertEqual(manifest_content, {"dummy.txt": "dummy.txt"})
|
self.assertEqual(manifest_content, {"dummy.txt": "dummy.txt"})
|
||||||
|
|
||||||
|
|
||||||
@override_settings(STATICFILES_STORAGE="staticfiles_tests.storage.NoneHashStorage")
|
@override_settings(
|
||||||
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": "staticfiles_tests.storage.NoneHashStorage",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
class TestCollectionNoneHashStorage(CollectionTestCase):
|
class TestCollectionNoneHashStorage(CollectionTestCase):
|
||||||
hashed_file_path = hashed_file_path
|
hashed_file_path = hashed_file_path
|
||||||
|
|
||||||
@ -569,7 +585,11 @@ class TestCollectionNoneHashStorage(CollectionTestCase):
|
|||||||
|
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
STATICFILES_STORAGE="staticfiles_tests.storage.NoPostProcessReplacedPathStorage"
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": "staticfiles_tests.storage.NoPostProcessReplacedPathStorage",
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
class TestCollectionNoPostProcessReplacedPaths(CollectionTestCase):
|
class TestCollectionNoPostProcessReplacedPaths(CollectionTestCase):
|
||||||
run_collectstatic_in_setUp = False
|
run_collectstatic_in_setUp = False
|
||||||
@ -580,7 +600,13 @@ class TestCollectionNoPostProcessReplacedPaths(CollectionTestCase):
|
|||||||
self.assertIn("post-processed", stdout.getvalue())
|
self.assertIn("post-processed", stdout.getvalue())
|
||||||
|
|
||||||
|
|
||||||
@override_settings(STATICFILES_STORAGE="staticfiles_tests.storage.SimpleStorage")
|
@override_settings(
|
||||||
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": "staticfiles_tests.storage.SimpleStorage",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
class TestCollectionSimpleStorage(CollectionTestCase):
|
class TestCollectionSimpleStorage(CollectionTestCase):
|
||||||
hashed_file_path = hashed_file_path
|
hashed_file_path = hashed_file_path
|
||||||
|
|
||||||
@ -733,7 +759,11 @@ class TestStaticFilePermissions(CollectionTestCase):
|
|||||||
@override_settings(
|
@override_settings(
|
||||||
FILE_UPLOAD_PERMISSIONS=0o655,
|
FILE_UPLOAD_PERMISSIONS=0o655,
|
||||||
FILE_UPLOAD_DIRECTORY_PERMISSIONS=0o765,
|
FILE_UPLOAD_DIRECTORY_PERMISSIONS=0o765,
|
||||||
STATICFILES_STORAGE="staticfiles_tests.test_storage.CustomStaticFilesStorage",
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": "staticfiles_tests.test_storage.CustomStaticFilesStorage",
|
||||||
|
},
|
||||||
|
},
|
||||||
)
|
)
|
||||||
def test_collect_static_files_subclass_of_static_storage(self):
|
def test_collect_static_files_subclass_of_static_storage(self):
|
||||||
call_command("collectstatic", **self.command_params)
|
call_command("collectstatic", **self.command_params)
|
||||||
@ -753,7 +783,11 @@ class TestStaticFilePermissions(CollectionTestCase):
|
|||||||
|
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
STATICFILES_STORAGE="django.contrib.staticfiles.storage.ManifestStaticFilesStorage",
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": "django.contrib.staticfiles.storage.ManifestStaticFilesStorage",
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
class TestCollectionHashedFilesCache(CollectionTestCase):
|
class TestCollectionHashedFilesCache(CollectionTestCase):
|
||||||
"""
|
"""
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
from django.conf import STATICFILES_STORAGE_ALIAS
|
||||||
from django.test import override_settings
|
from django.test import override_settings
|
||||||
|
|
||||||
from .cases import StaticFilesTestCase
|
from .cases import StaticFilesTestCase
|
||||||
@ -12,7 +13,11 @@ class TestTemplateTag(StaticFilesTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
STATICFILES_STORAGE="staticfiles_tests.storage.QueryStringStorage"
|
STORAGES={
|
||||||
|
STATICFILES_STORAGE_ALIAS: {
|
||||||
|
"BACKEND": "staticfiles_tests.storage.QueryStringStorage"
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
def test_template_tag_escapes(self):
|
def test_template_tag_escapes(self):
|
||||||
"""
|
"""
|
||||||
|
@ -5,7 +5,7 @@ import warnings
|
|||||||
from io import StringIO
|
from io import StringIO
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import STATICFILES_STORAGE_ALIAS, settings
|
||||||
from django.contrib.staticfiles.finders import get_finder, get_finders
|
from django.contrib.staticfiles.finders import get_finder, get_finders
|
||||||
from django.contrib.staticfiles.storage import staticfiles_storage
|
from django.contrib.staticfiles.storage import staticfiles_storage
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
@ -2106,12 +2106,14 @@ class OverrideSettingsTests(SimpleTestCase):
|
|||||||
|
|
||||||
def test_override_staticfiles_storage(self):
|
def test_override_staticfiles_storage(self):
|
||||||
"""
|
"""
|
||||||
Overriding the STATICFILES_STORAGE setting should be reflected in
|
Overriding the STORAGES setting should be reflected in
|
||||||
the value of django.contrib.staticfiles.storage.staticfiles_storage.
|
the value of django.contrib.staticfiles.storage.staticfiles_storage.
|
||||||
"""
|
"""
|
||||||
new_class = "ManifestStaticFilesStorage"
|
new_class = "ManifestStaticFilesStorage"
|
||||||
new_storage = "django.contrib.staticfiles.storage." + new_class
|
new_storage = "django.contrib.staticfiles.storage." + new_class
|
||||||
with self.settings(STATICFILES_STORAGE=new_storage):
|
with self.settings(
|
||||||
|
STORAGES={STATICFILES_STORAGE_ALIAS: {"BACKEND": new_storage}}
|
||||||
|
):
|
||||||
self.assertEqual(staticfiles_storage.__class__.__name__, new_class)
|
self.assertEqual(staticfiles_storage.__class__.__name__, new_class)
|
||||||
|
|
||||||
def test_override_staticfiles_finders(self):
|
def test_override_staticfiles_finders(self):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user