Fixed #28606 -- Deprecated CachedStaticFilesStorage.
This commit is contained in:
parent
55b0b766fb
commit
f892781b95
|
@ -3,6 +3,7 @@ import json
|
||||||
import os
|
import os
|
||||||
import posixpath
|
import posixpath
|
||||||
import re
|
import re
|
||||||
|
import warnings
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from urllib.parse import unquote, urldefrag, urlsplit, urlunsplit
|
from urllib.parse import unquote, urldefrag, urlsplit, urlunsplit
|
||||||
|
|
||||||
|
@ -14,6 +15,7 @@ from django.core.cache import (
|
||||||
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, get_storage_class
|
||||||
|
from django.utils.deprecation import RemovedInDjango31Warning
|
||||||
from django.utils.functional import LazyObject
|
from django.utils.functional import LazyObject
|
||||||
|
|
||||||
|
|
||||||
|
@ -474,7 +476,13 @@ class CachedStaticFilesStorage(CachedFilesMixin, StaticFilesStorage):
|
||||||
A static file system storage backend which also saves
|
A static file system storage backend which also saves
|
||||||
hashed copies of the files it saves.
|
hashed copies of the files it saves.
|
||||||
"""
|
"""
|
||||||
pass
|
def __init__(self, *args, **kwargs):
|
||||||
|
warnings.warn(
|
||||||
|
'CachedStaticFilesStorage is deprecated in favor of '
|
||||||
|
'ManifestStaticFilesStorage.',
|
||||||
|
RemovedInDjango31Warning, stacklevel=2,
|
||||||
|
)
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class ManifestStaticFilesStorage(ManifestFilesMixin, StaticFilesStorage):
|
class ManifestStaticFilesStorage(ManifestFilesMixin, StaticFilesStorage):
|
||||||
|
|
|
@ -26,6 +26,9 @@ details on these changes.
|
||||||
|
|
||||||
* The ``FILE_CHARSET`` setting will be removed.
|
* The ``FILE_CHARSET`` setting will be removed.
|
||||||
|
|
||||||
|
* ``django.contrib.staticfiles.storage.CachedStaticFilesStorage`` will be
|
||||||
|
removed.
|
||||||
|
|
||||||
.. _deprecation-removed-in-3.0:
|
.. _deprecation-removed-in-3.0:
|
||||||
|
|
||||||
3.0
|
3.0
|
||||||
|
|
|
@ -62,7 +62,7 @@ The :djadmin:`collectstatic` management command calls the
|
||||||
method of the :setting:`STATICFILES_STORAGE` after each run and passes
|
method of the :setting:`STATICFILES_STORAGE` after each run and passes
|
||||||
a list of paths that have been found by the management command. It also
|
a list of paths that have been found by the management command. It also
|
||||||
receives all command line options of :djadmin:`collectstatic`. This is used
|
receives all command line options of :djadmin:`collectstatic`. This is used
|
||||||
by the :class:`~django.contrib.staticfiles.storage.CachedStaticFilesStorage`
|
by the :class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage`
|
||||||
by default.
|
by default.
|
||||||
|
|
||||||
By default, collected files receive permissions from
|
By default, collected files receive permissions from
|
||||||
|
@ -229,9 +229,7 @@ local development, should **never be used in production** and is only
|
||||||
available if the :doc:`staticfiles </ref/contrib/staticfiles>` app is
|
available if the :doc:`staticfiles </ref/contrib/staticfiles>` app is
|
||||||
in your project's :setting:`INSTALLED_APPS` setting.
|
in your project's :setting:`INSTALLED_APPS` setting.
|
||||||
|
|
||||||
``--insecure`` doesn't work with
|
``--insecure`` doesn't work with :class:`~.storage.ManifestStaticFilesStorage`.
|
||||||
:class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage` or
|
|
||||||
:class:`~django.contrib.staticfiles.storage.CachedStaticFilesStorage`.
|
|
||||||
|
|
||||||
Example usage::
|
Example usage::
|
||||||
|
|
||||||
|
@ -262,7 +260,7 @@ line options. It yields tuples of three values:
|
||||||
``processed`` is a boolean indicating whether or not the value was
|
``processed`` is a boolean indicating whether or not the value was
|
||||||
post-processed, or an exception if post-processing failed.
|
post-processed, or an exception if post-processing failed.
|
||||||
|
|
||||||
The :class:`~django.contrib.staticfiles.storage.CachedStaticFilesStorage`
|
The :class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage`
|
||||||
uses this behind the scenes to replace the paths with their hashed
|
uses this behind the scenes to replace the paths with their hashed
|
||||||
counterparts and update the cache appropriately.
|
counterparts and update the cache appropriately.
|
||||||
|
|
||||||
|
@ -362,6 +360,13 @@ hashing algorithm.
|
||||||
|
|
||||||
.. class:: storage.CachedStaticFilesStorage
|
.. class:: storage.CachedStaticFilesStorage
|
||||||
|
|
||||||
|
.. deprecated:: 2.1
|
||||||
|
|
||||||
|
``CachedStaticFilesStorage`` is deprecated as it has some intractable
|
||||||
|
problems, some of which are outlined below. Use
|
||||||
|
:class:`~storage.ManifestStaticFilesStorage` or a third-party cloud storage
|
||||||
|
instead.
|
||||||
|
|
||||||
``CachedStaticFilesStorage`` is a similar class like the
|
``CachedStaticFilesStorage`` is a similar class like the
|
||||||
:class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage` class
|
:class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage` class
|
||||||
but uses Django's :doc:`caching framework</topics/cache>` for storing the
|
but uses Django's :doc:`caching framework</topics/cache>` for storing the
|
||||||
|
|
|
@ -466,15 +466,12 @@ files from a cloud service<staticfiles-from-cdn>`.
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
The :mod:`staticfiles<django.contrib.staticfiles>` contrib app now has a
|
The :mod:`staticfiles<django.contrib.staticfiles>` contrib app now has a
|
||||||
:class:`~django.contrib.staticfiles.storage.CachedStaticFilesStorage` backend
|
``django.contrib.staticfiles.storage.CachedStaticFilesStorage`` backend
|
||||||
that caches the files it saves (when running the :djadmin:`collectstatic`
|
that caches the files it saves (when running the :djadmin:`collectstatic`
|
||||||
management command) by appending the MD5 hash of the file's content to the
|
management command) by appending the MD5 hash of the file's content to the
|
||||||
filename. For example, the file ``css/styles.css`` would also be saved as
|
filename. For example, the file ``css/styles.css`` would also be saved as
|
||||||
``css/styles.55e7cbb9ba48.css``
|
``css/styles.55e7cbb9ba48.css``
|
||||||
|
|
||||||
See the :class:`~django.contrib.staticfiles.storage.CachedStaticFilesStorage`
|
|
||||||
docs for more information.
|
|
||||||
|
|
||||||
Simple clickjacking protection
|
Simple clickjacking protection
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
|
|
|
@ -506,8 +506,7 @@ Minor features
|
||||||
and :attr:`~django.core.files.storage.FileSystemStorage.directory_permissions_mode`
|
and :attr:`~django.core.files.storage.FileSystemStorage.directory_permissions_mode`
|
||||||
parameters. See :djadmin:`collectstatic` for example usage.
|
parameters. See :djadmin:`collectstatic` for example usage.
|
||||||
|
|
||||||
* The :class:`~django.contrib.staticfiles.storage.CachedStaticFilesStorage`
|
* The ``CachedStaticFilesStorage`` backend gets a sibling class called
|
||||||
backend gets a sibling class called
|
|
||||||
:class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage`
|
:class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage`
|
||||||
that doesn't use the cache system at all but instead a JSON file called
|
that doesn't use the cache system at all but instead a JSON file called
|
||||||
``staticfiles.json`` for storing the mapping between the original file name
|
``staticfiles.json`` for storing the mapping between the original file name
|
||||||
|
|
|
@ -354,3 +354,7 @@ Miscellaneous
|
||||||
|
|
||||||
* The ``FILE_CHARSET`` setting is deprecated. Starting with Django 3.1, files
|
* The ``FILE_CHARSET`` setting is deprecated. Starting with Django 3.1, files
|
||||||
read from disk must be UTF-8 encoded.
|
read from disk must be UTF-8 encoded.
|
||||||
|
|
||||||
|
* ``django.contrib.staticfiles.storage.CachedStaticFilesStorage`` is
|
||||||
|
deprecated due to the intractable problems that is has. Use
|
||||||
|
:class:`.ManifestStaticFilesStorage` or a third-party cloud storage instead.
|
||||||
|
|
|
@ -290,13 +290,13 @@ Static files
|
||||||
Static files, which by definition are not dynamic, make an excellent target for
|
Static files, which by definition are not dynamic, make an excellent target for
|
||||||
optimization gains.
|
optimization gains.
|
||||||
|
|
||||||
:class:`~django.contrib.staticfiles.storage.CachedStaticFilesStorage`
|
:class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage`
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
By taking advantage of web browsers' caching abilities, you can
|
By taking advantage of web browsers' caching abilities, you can
|
||||||
eliminate network hits entirely for a given file after the initial download.
|
eliminate network hits entirely for a given file after the initial download.
|
||||||
|
|
||||||
:class:`~django.contrib.staticfiles.storage.CachedStaticFilesStorage` appends a
|
:class:`~django.contrib.staticfiles.storage.ManifestStaticFilesStorage` appends a
|
||||||
content-dependent tag to the filenames of :doc:`static files
|
content-dependent tag to the filenames of :doc:`static files
|
||||||
</ref/contrib/staticfiles>` to make it safe for browsers to cache them
|
</ref/contrib/staticfiles>` to make it safe for browsers to cache them
|
||||||
long-term without missing future changes - when a file changes, so will the
|
long-term without missing future changes - when a file changes, so will the
|
||||||
|
|
|
@ -2,7 +2,7 @@ import os
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.staticfiles.storage import CachedStaticFilesStorage
|
from django.contrib.staticfiles.storage import ManifestStaticFilesStorage
|
||||||
from django.core.files import storage
|
from django.core.files import storage
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
|
@ -70,18 +70,18 @@ class QueryStringStorage(storage.Storage):
|
||||||
return path + '?a=b&c=d'
|
return path + '?a=b&c=d'
|
||||||
|
|
||||||
|
|
||||||
class SimpleCachedStaticFilesStorage(CachedStaticFilesStorage):
|
class SimpleStorage(ManifestStaticFilesStorage):
|
||||||
|
|
||||||
def file_hash(self, name, content=None):
|
def file_hash(self, name, content=None):
|
||||||
return 'deploy12345'
|
return 'deploy12345'
|
||||||
|
|
||||||
|
|
||||||
class ExtraPatternsCachedStaticFilesStorage(CachedStaticFilesStorage):
|
class ExtraPatternsStorage(ManifestStaticFilesStorage):
|
||||||
"""
|
"""
|
||||||
A storage class to test pattern substitutions with more than one pattern
|
A storage class to test pattern substitutions with more than one pattern
|
||||||
entry. The added pattern rewrites strings like "url(...)" to JS_URL("...").
|
entry. The added pattern rewrites strings like "url(...)" to JS_URL("...").
|
||||||
"""
|
"""
|
||||||
patterns = tuple(CachedStaticFilesStorage.patterns) + (
|
patterns = tuple(ManifestStaticFilesStorage.patterns) + (
|
||||||
(
|
(
|
||||||
"*.js", (
|
"*.js", (
|
||||||
(r"""(url\(['"]{0,1}\s*(.*?)["']{0,1}\))""", 'JS_URL("%s")'),
|
(r"""(url\(['"]{0,1}\s*(.*?)["']{0,1}\))""", 'JS_URL("%s")'),
|
||||||
|
|
|
@ -201,13 +201,13 @@ class TestCollectionVerbosity(CollectionTestCase):
|
||||||
self.assertIn(self.staticfiles_copied_msg, output)
|
self.assertIn(self.staticfiles_copied_msg, output)
|
||||||
self.assertIn(self.copying_msg, output)
|
self.assertIn(self.copying_msg, output)
|
||||||
|
|
||||||
@override_settings(STATICFILES_STORAGE='django.contrib.staticfiles.storage.CachedStaticFilesStorage')
|
@override_settings(STATICFILES_STORAGE='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()
|
||||||
self.run_collectstatic(verbosity=1, stdout=stdout, post_process=True)
|
self.run_collectstatic(verbosity=1, stdout=stdout, post_process=True)
|
||||||
self.assertNotIn(self.post_process_msg, stdout.getvalue())
|
self.assertNotIn(self.post_process_msg, stdout.getvalue())
|
||||||
|
|
||||||
@override_settings(STATICFILES_STORAGE='django.contrib.staticfiles.storage.CachedStaticFilesStorage')
|
@override_settings(STATICFILES_STORAGE='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()
|
||||||
self.run_collectstatic(verbosity=2, stdout=stdout, post_process=True)
|
self.run_collectstatic(verbosity=2, stdout=stdout, post_process=True)
|
||||||
|
|
|
@ -12,7 +12,8 @@ from django.contrib.staticfiles.management.commands.collectstatic import (
|
||||||
)
|
)
|
||||||
from django.core.cache.backends.base import BaseCache
|
from django.core.cache.backends.base import BaseCache
|
||||||
from django.core.management import call_command
|
from django.core.management import call_command
|
||||||
from django.test import override_settings
|
from django.test import SimpleTestCase, ignore_warnings, override_settings
|
||||||
|
from django.utils.deprecation import RemovedInDjango31Warning
|
||||||
|
|
||||||
from .cases import CollectionTestCase
|
from .cases import CollectionTestCase
|
||||||
from .settings import TEST_ROOT
|
from .settings import TEST_ROOT
|
||||||
|
@ -43,9 +44,6 @@ class TestHashedFiles:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def test_template_tag_return(self):
|
def test_template_tag_return(self):
|
||||||
"""
|
|
||||||
Test the CachedStaticFilesStorage backend.
|
|
||||||
"""
|
|
||||||
self.assertStaticRaises(ValueError, "does/not/exist.png", "/static/does/not/exist.png")
|
self.assertStaticRaises(ValueError, "does/not/exist.png", "/static/does/not/exist.png")
|
||||||
self.assertStaticRenders("test/file.txt", "/static/test/file.dad0999e4f8f.txt")
|
self.assertStaticRenders("test/file.txt", "/static/test/file.dad0999e4f8f.txt")
|
||||||
self.assertStaticRenders("test/file.txt", "/static/test/file.dad0999e4f8f.txt", asvar=True)
|
self.assertStaticRenders("test/file.txt", "/static/test/file.dad0999e4f8f.txt", asvar=True)
|
||||||
|
@ -232,6 +230,7 @@ class TestHashedFiles:
|
||||||
self.assertPostCondition()
|
self.assertPostCondition()
|
||||||
|
|
||||||
|
|
||||||
|
@ignore_warnings(category=RemovedInDjango31Warning)
|
||||||
@override_settings(
|
@override_settings(
|
||||||
STATICFILES_STORAGE='django.contrib.staticfiles.storage.CachedStaticFilesStorage',
|
STATICFILES_STORAGE='django.contrib.staticfiles.storage.CachedStaticFilesStorage',
|
||||||
)
|
)
|
||||||
|
@ -299,10 +298,20 @@ class TestCollectionCachedStorage(TestHashedFiles, CollectionTestCase):
|
||||||
self.hashed_file_path('cached/styles.css')
|
self.hashed_file_path('cached/styles.css')
|
||||||
|
|
||||||
|
|
||||||
@override_settings(
|
class TestCachedStaticFilesStorageDeprecation(SimpleTestCase):
|
||||||
STATICFILES_STORAGE='staticfiles_tests.storage.ExtraPatternsCachedStaticFilesStorage',
|
def test_warning(self):
|
||||||
|
from django.contrib.staticfiles.storage import CachedStaticFilesStorage
|
||||||
|
from django.utils.deprecation import RemovedInDjango31Warning
|
||||||
|
msg = (
|
||||||
|
'CachedStaticFilesStorage is deprecated in favor of '
|
||||||
|
'ManifestStaticFilesStorage.'
|
||||||
)
|
)
|
||||||
class TestExtraPatternsCachedStorage(CollectionTestCase):
|
with self.assertRaisesMessage(RemovedInDjango31Warning, msg):
|
||||||
|
CachedStaticFilesStorage()
|
||||||
|
|
||||||
|
|
||||||
|
@override_settings(STATICFILES_STORAGE='staticfiles_tests.storage.ExtraPatternsStorage')
|
||||||
|
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
|
||||||
|
@ -437,13 +446,8 @@ class TestCollectionManifestStorage(TestHashedFiles, CollectionTestCase):
|
||||||
self.hashed_file_path(missing_file_name)
|
self.hashed_file_path(missing_file_name)
|
||||||
|
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(STATICFILES_STORAGE='staticfiles_tests.storage.SimpleStorage')
|
||||||
STATICFILES_STORAGE='staticfiles_tests.storage.SimpleCachedStaticFilesStorage',
|
class TestCollectionSimpleStorage(CollectionTestCase):
|
||||||
)
|
|
||||||
class TestCollectionSimpleCachedStorage(CollectionTestCase):
|
|
||||||
"""
|
|
||||||
Tests for the Cache busting storage
|
|
||||||
"""
|
|
||||||
hashed_file_path = hashed_file_path
|
hashed_file_path = hashed_file_path
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -451,9 +455,6 @@ class TestCollectionSimpleCachedStorage(CollectionTestCase):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
|
|
||||||
def test_template_tag_return(self):
|
def test_template_tag_return(self):
|
||||||
"""
|
|
||||||
Test the CachedStaticFilesStorage backend.
|
|
||||||
"""
|
|
||||||
self.assertStaticRaises(ValueError, "does/not/exist.png", "/static/does/not/exist.png")
|
self.assertStaticRaises(ValueError, "does/not/exist.png", "/static/does/not/exist.png")
|
||||||
self.assertStaticRenders("test/file.txt", "/static/test/file.deploy12345.txt")
|
self.assertStaticRenders("test/file.txt", "/static/test/file.deploy12345.txt")
|
||||||
self.assertStaticRenders("cached/styles.css", "/static/cached/styles.deploy12345.css")
|
self.assertStaticRenders("cached/styles.css", "/static/cached/styles.deploy12345.css")
|
||||||
|
@ -543,7 +544,7 @@ class TestStaticFilePermissions(CollectionTestCase):
|
||||||
|
|
||||||
|
|
||||||
@override_settings(
|
@override_settings(
|
||||||
STATICFILES_STORAGE='django.contrib.staticfiles.storage.CachedStaticFilesStorage',
|
STATICFILES_STORAGE='django.contrib.staticfiles.storage.ManifestStaticFilesStorage',
|
||||||
)
|
)
|
||||||
class TestCollectionHashedFilesCache(CollectionTestCase):
|
class TestCollectionHashedFilesCache(CollectionTestCase):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1092,7 +1092,7 @@ class OverrideSettingsTests(SimpleTestCase):
|
||||||
Overriding the STATICFILES_STORAGE setting should be reflected in
|
Overriding the STATICFILES_STORAGE 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 = 'CachedStaticFilesStorage'
|
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(STATICFILES_STORAGE=new_storage):
|
||||||
self.assertEqual(staticfiles_storage.__class__.__name__, new_class)
|
self.assertEqual(staticfiles_storage.__class__.__name__, new_class)
|
||||||
|
|
Loading…
Reference in New Issue