Fixed #28606 -- Deprecated CachedStaticFilesStorage.

This commit is contained in:
Tim Graham 2018-10-27 10:30:28 -04:00
parent 55b0b766fb
commit f892781b95
11 changed files with 58 additions and 41 deletions

View File

@ -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):

View File

@ -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

View File

@ -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

View File

@ -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
------------------------------ ------------------------------

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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")'),

View File

@ -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)

View File

@ -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):
""" """

View File

@ -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)