From b02f08e02c34bcf19444c15b54c5f64ddd4c9ef2 Mon Sep 17 00:00:00 2001
From: Tom Christie <tom@tomchristie.com>
Date: Wed, 2 Sep 2015 13:20:46 +0100
Subject: [PATCH] Fixed #25034 -- Converted caches ImproperlyConfigured error
 to a system check.

---
 django/core/cache/__init__.py        |  4 ----
 django/core/checks/__init__.py       |  1 +
 django/core/checks/caches.py         | 18 ++++++++++++++
 django/core/checks/registry.py       |  1 +
 docs/ref/checks.txt                  | 10 ++++++++
 tests/check_framework/test_caches.py | 35 ++++++++++++++++++++++++++++
 6 files changed, 65 insertions(+), 4 deletions(-)
 create mode 100644 django/core/checks/caches.py
 create mode 100644 tests/check_framework/test_caches.py

diff --git a/django/core/cache/__init__.py b/django/core/cache/__init__.py
index 93a887a058..26897ff850 100644
--- a/django/core/cache/__init__.py
+++ b/django/core/cache/__init__.py
@@ -19,7 +19,6 @@ from django.core import signals
 from django.core.cache.backends.base import (
     BaseCache, CacheKeyWarning, InvalidCacheBackendError,
 )
-from django.core.exceptions import ImproperlyConfigured
 from django.utils.module_loading import import_string
 
 __all__ = [
@@ -29,9 +28,6 @@ __all__ = [
 
 DEFAULT_CACHE_ALIAS = 'default'
 
-if DEFAULT_CACHE_ALIAS not in settings.CACHES:
-    raise ImproperlyConfigured("You must define a '%s' cache" % DEFAULT_CACHE_ALIAS)
-
 
 def _create_cache(backend, **kwargs):
     try:
diff --git a/django/core/checks/__init__.py b/django/core/checks/__init__.py
index 2fe7998f83..dec2446ae2 100644
--- a/django/core/checks/__init__.py
+++ b/django/core/checks/__init__.py
@@ -8,6 +8,7 @@ from .messages import (
 from .registry import Tags, register, run_checks, tag_exists
 
 # Import these to force registration of checks
+import django.core.checks.caches  # NOQA isort:skip
 import django.core.checks.compatibility.django_1_8_0  # NOQA isort:skip
 import django.core.checks.model_checks  # NOQA isort:skip
 import django.core.checks.security.base  # NOQA isort:skip
diff --git a/django/core/checks/caches.py b/django/core/checks/caches.py
new file mode 100644
index 0000000000..4a4141777d
--- /dev/null
+++ b/django/core/checks/caches.py
@@ -0,0 +1,18 @@
+from __future__ import unicode_literals
+
+from django.conf import settings
+from django.core.cache import DEFAULT_CACHE_ALIAS
+
+from . import Error, Tags, register
+
+E001 = Error(
+    "You must define a '%s' cache in your CACHES setting." % DEFAULT_CACHE_ALIAS,
+    id='caches.E001',
+)
+
+
+@register(Tags.caches)
+def check_default_cache_is_configured(app_configs, **kwargs):
+    if DEFAULT_CACHE_ALIAS not in settings.CACHES:
+        return [E001]
+    return []
diff --git a/django/core/checks/registry.py b/django/core/checks/registry.py
index dbd3a6d36f..96df429dc9 100644
--- a/django/core/checks/registry.py
+++ b/django/core/checks/registry.py
@@ -11,6 +11,7 @@ class Tags(object):
     Built-in tags for internal checks.
     """
     admin = 'admin'
+    caches = 'caches'
     compatibility = 'compatibility'
     models = 'models'
     security = 'security'
diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt
index 226db547a0..31f9a297cd 100644
--- a/docs/ref/checks.txt
+++ b/docs/ref/checks.txt
@@ -80,6 +80,7 @@ Django's system checks are organized using the following tags:
 * ``compatibility``: Flagging potential problems with version upgrades.
 * ``security``: Checks security related configuration.
 * ``templates``: Checks template related configuration.
+* ``caches``: Checks cache related configuration.
 
 Some checks may be registered with multiple tags.
 
@@ -569,3 +570,12 @@ configured:
 * **templates.E001**: You have ``'APP_DIRS': True`` in your
   :setting:`TEMPLATES` but also specify ``'loaders'`` in ``OPTIONS``. Either
   remove ``APP_DIRS`` or remove the ``'loaders'`` option.
+
+Caches
+------
+
+The following checks verify that your :setting:`CACHES` setting is correctly
+configured:
+
+* **caches.E001**: You must define a ``'default'`` cache in your
+  :setting:`CACHES` setting.
diff --git a/tests/check_framework/test_caches.py b/tests/check_framework/test_caches.py
new file mode 100644
index 0000000000..ab16c6071c
--- /dev/null
+++ b/tests/check_framework/test_caches.py
@@ -0,0 +1,35 @@
+from django.core.checks.caches import E001
+from django.test import SimpleTestCase
+from django.test.utils import override_settings
+
+
+class CheckCacheSettingsAppDirsTest(SimpleTestCase):
+    VALID_CACHES_CONFIGURATION = {
+        'default': {
+            'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
+        },
+    }
+    INVALID_CACHES_CONFIGURATION = {
+        'other': {
+            'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
+        },
+    }
+
+    @property
+    def func(self):
+        from django.core.checks.caches import check_default_cache_is_configured
+        return check_default_cache_is_configured
+
+    @override_settings(CACHES=VALID_CACHES_CONFIGURATION)
+    def test_default_cache_included(self):
+        """
+        Don't error if 'default' is present in CACHES setting.
+        """
+        self.assertEqual(self.func(None), [])
+
+    @override_settings(CACHES=INVALID_CACHES_CONFIGURATION)
+    def test_default_cache_not_included(self):
+        """
+        Error if 'default' not present in CACHES setting.
+        """
+        self.assertEqual(self.func(None), [E001])