diff --git a/django/core/checks/caches.py b/django/core/checks/caches.py index 6fdecf5a1e..4baa23aeb6 100644 --- a/django/core/checks/caches.py +++ b/django/core/checks/caches.py @@ -53,3 +53,19 @@ def check_cache_location_not_exposed(app_configs, **kwargs): id='caches.W002', )) return errors + + +@register(Tags.caches) +def check_file_based_cache_is_absolute(app_configs, **kwargs): + errors = [] + for alias, config in settings.CACHES.items(): + cache = caches[alias] + if not isinstance(cache, FileBasedCache): + continue + if not pathlib.Path(config['LOCATION']).is_absolute(): + errors.append(Warning( + f"Your '{alias}' cache LOCATION path is relative. Use an " + f"absolute path instead.", + id='caches.W003', + )) + return errors diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt index 0ff6d36a25..b7f941ff83 100644 --- a/docs/ref/checks.txt +++ b/docs/ref/checks.txt @@ -142,6 +142,8 @@ configured: lead to corruption of your data because its :setting:`LOCATION ` matches/is inside/contains :setting:`MEDIA_ROOT`/:setting:`STATIC_ROOT`/:setting:`STATICFILES_DIRS`. +* **caches.W003**: Your ```` cache :setting:`LOCATION ` + is relative. Use an absolute path instead. Database -------- diff --git a/tests/check_framework/test_caches.py b/tests/check_framework/test_caches.py index 002528d1f5..a3ddfd64e7 100644 --- a/tests/check_framework/test_caches.py +++ b/tests/check_framework/test_caches.py @@ -3,6 +3,7 @@ import pathlib from django.core.checks import Warning from django.core.checks.caches import ( E001, check_cache_location_not_exposed, check_default_cache_is_configured, + check_file_based_cache_is_absolute, ) from django.test import SimpleTestCase from django.test.utils import override_settings @@ -89,3 +90,29 @@ class CheckCacheLocationTest(SimpleTestCase): settings = self.get_settings(setting, root / 'cache', root / 'other') with self.subTest(setting=setting), self.settings(**settings): self.assertEqual(check_cache_location_not_exposed(None), []) + + +class CheckCacheAbsolutePath(SimpleTestCase): + def test_absolute_path(self): + with self.settings(CACHES={ + 'default': { + 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', + 'LOCATION': pathlib.Path.cwd() / 'cache', + }, + }): + self.assertEqual(check_file_based_cache_is_absolute(None), []) + + def test_relative_path(self): + with self.settings(CACHES={ + 'default': { + 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', + 'LOCATION': 'cache', + }, + }): + self.assertEqual(check_file_based_cache_is_absolute(None), [ + Warning( + "Your 'default' cache LOCATION path is relative. Use an " + "absolute path instead.", + id='caches.W003', + ), + ])