diff --git a/django/conf/__init__.py b/django/conf/__init__.py
index 6272f4e..ad8a1cf 100644
--- a/django/conf/__init__.py
+++ b/django/conf/__init__.py
@@ -143,6 +143,13 @@ class Settings(BaseSettings):
             # Backwards-compatibility shim for #16288 fix
             compat_patch_logging_config(self.LOGGING)
 
+            def check_in_dict(key1, key2):
+                if not key2 in self.LOGGING.get(key1, {}):
+                    self.LOGGING[key1][key2] = global_settings.LOGGING[key1][key2]
+            check_in_dict('filters', 'require_debug_true')
+            check_in_dict('handlers', 'console')
+            check_in_dict('loggers', 'django')
+
             # ... then invoke it with the logging settings
             logging_config_func(self.LOGGING)
 
diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py
index 13f7991..2274f9a 100644
--- a/django/conf/global_settings.py
+++ b/django/conf/global_settings.py
@@ -559,9 +559,16 @@ LOGGING = {
     'filters': {
         'require_debug_false': {
             '()': 'django.utils.log.RequireDebugFalse',
-        }
+        },
+        'require_debug_true': {
+            '()': 'django.utils.log.RequireDebugTrue',
+        },
     },
     'handlers': {
+        'console':{
+            'level': 'INFO',
+            'class': 'logging.StreamHandler',
+        },
         'mail_admins': {
             'level': 'ERROR',
             'filters': ['require_debug_false'],
@@ -569,6 +576,10 @@ LOGGING = {
         }
     },
     'loggers': {
+        'django': {
+            'handlers': ['console'],
+            'filters': ['require_debug_true'],
+        },
         'django.request': {
             'handlers': ['mail_admins'],
             'level': 'ERROR',
diff --git a/django/utils/log.py b/django/utils/log.py
index df2089f..2400de2 100644
--- a/django/utils/log.py
+++ b/django/utils/log.py
@@ -21,16 +21,9 @@ try:
 except ImportError:
     from django.utils.dictconfig import dictConfig
 
+# This is a remainder of an old 2.4 shim: to be deprecated or simply removed
 getLogger = logging.getLogger
 
-# Ensure the creation of the Django logger
-# with a null handler. This ensures we don't get any
-# 'No handlers could be found for logger "django"' messages
-logger = getLogger('django')
-if not logger.handlers:
-    logger.addHandler(NullHandler())
-
-
 class AdminEmailHandler(logging.Handler):
     """An exception log handler that emails log entries to site admins.
 
@@ -103,3 +96,8 @@ class CallbackFilter(logging.Filter):
 class RequireDebugFalse(logging.Filter):
     def filter(self, record):
         return not settings.DEBUG
+
+
+class RequireDebugTrue(logging.Filter):
+    def filter(self, record):
+       return settings.DEBUG
diff --git a/tests/regressiontests/logging_tests/tests.py b/tests/regressiontests/logging_tests/tests.py
index f444e0f..dd2fc82 100644
--- a/tests/regressiontests/logging_tests/tests.py
+++ b/tests/regressiontests/logging_tests/tests.py
@@ -9,6 +9,7 @@ from django.core import mail
 from django.test import TestCase, RequestFactory
 from django.test.utils import override_settings
 from django.utils.log import CallbackFilter, RequireDebugFalse
+from django.utils.six import StringIO
 
 
 # logging config prior to using filter with mail_admins
@@ -107,6 +108,28 @@ class PatchLoggingConfigTest(TestCase):
         self.assertEqual(config, new_config)
 
 
+class DefaultLoggingTest(TestCase):
+    def setUp(self):
+        self.logger = logging.getLogger('django')
+        self.old_stream = self.logger.handlers[0].stream
+
+    def tearDown(self):
+        self.logger.handlers[0].stream = self.old_stream
+
+    def test_django_logger(self):
+        """
+        The 'django' base logger only output anything when DEBUG=True.
+        """
+        output = StringIO()
+        self.logger.handlers[0].stream = output
+        self.logger.error("Hey, this is an error.")
+        self.assertEqual(output.getvalue(), '')
+
+        with self.settings(DEBUG=True):
+            self.logger.error("Hey, this is an error.")
+            self.assertEqual(output.getvalue(), 'Hey, this is an error.\n')
+
+
 class CallbackFilterTest(TestCase):
     def test_sense(self):
         f_false = CallbackFilter(lambda r: False)
@@ -129,6 +152,13 @@ class CallbackFilterTest(TestCase):
 
 
 class AdminEmailHandlerTest(TestCase):
+    def setUp(self):
+        self.logger = logging.getLogger('django.request')
+        self.old_propagate = self.logger.propagate
+        self.logger.propagate = False
+
+    def tearDown(self):
+        self.logger.propagate =  self.old_propagate
 
     def get_admin_email_handler(self, logger):
         # Inspired from regressiontests/views/views.py: send_log()
@@ -154,14 +184,13 @@ class AdminEmailHandlerTest(TestCase):
         token1 = 'ping'
         token2 = 'pong'
 
-        logger = logging.getLogger('django.request')
-        admin_email_handler = self.get_admin_email_handler(logger)
+        admin_email_handler = self.get_admin_email_handler(self.logger)
         # Backup then override original filters
         orig_filters = admin_email_handler.filters
         try:
             admin_email_handler.filters = []
 
-            logger.error(message, token1, token2)
+            self.logger.error(message, token1, token2)
 
             self.assertEqual(len(mail.outbox), 1)
             self.assertEqual(mail.outbox[0].to, ['admin@example.com'])
@@ -185,15 +214,14 @@ class AdminEmailHandlerTest(TestCase):
         token1 = 'ping'
         token2 = 'pong'
 
-        logger = logging.getLogger('django.request')
-        admin_email_handler = self.get_admin_email_handler(logger)
+        admin_email_handler = self.get_admin_email_handler(self.logger)
         # Backup then override original filters
         orig_filters = admin_email_handler.filters
         try:
             admin_email_handler.filters = []
             rf = RequestFactory()
             request = rf.get('/')
-            logger.error(message, token1, token2,
+            self.logger.error(message, token1, token2,
                 extra={
                     'status_code': 403,
                     'request': request,
@@ -223,8 +251,7 @@ class AdminEmailHandlerTest(TestCase):
 
         self.assertEqual(len(mail.outbox), 0)
 
-        logger = logging.getLogger('django.request')
-        logger.error(message)
+        self.logger.error(message)
 
         self.assertEqual(len(mail.outbox), 1)
         self.assertFalse('\n' in mail.outbox[0].subject)
@@ -248,8 +275,7 @@ class AdminEmailHandlerTest(TestCase):
 
         self.assertEqual(len(mail.outbox), 0)
 
-        logger = logging.getLogger('django.request')
-        logger.error(message)
+        self.logger.error(message)
 
         self.assertEqual(len(mail.outbox), 1)
         self.assertEqual(mail.outbox[0].subject, expected_subject)
diff --git a/tests/regressiontests/views/views.py b/tests/regressiontests/views/views.py
index 2836d1b..f4e7a5c 100644
--- a/tests/regressiontests/views/views.py
+++ b/tests/regressiontests/views/views.py
@@ -119,6 +119,7 @@ def raises_template_does_not_exist(request):
 
 def send_log(request, exc_info):
     logger = getLogger('django.request')
+    logger.propagate = False
     # The default logging config has a logging filter to ensure admin emails are
     # only sent with DEBUG=False, but since someone might choose to remove that
     # filter, we still want to be able to test the behavior of error emails
@@ -227,4 +228,4 @@ class Klass(object):
             return technical_500_response(request, *exc_info)
 
 def sensitive_method_view(request):
-    return Klass().method(request)
\ No newline at end of file
+    return Klass().method(request)
