summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincenzo Pandolfo <pandolfovince@gmail.com>2015-12-10 12:45:21 +0000
committerTim Graham <timograham@gmail.com>2016-01-22 18:29:56 -0500
commit0490d72f2a309ee2c6d73cdc5aa5cc381e14ae98 (patch)
treed41cba82ed4b6154acedac8d2b3ba269347ec4d8
parent956cde800490d2d9e1e5fcc83755a9226de27f24 (diff)
Fixed #24116 -- Moved AdminSite.check_dependencies() to system checks.
-rw-r--r--django/contrib/admin/apps.py3
-rw-r--r--django/contrib/admin/checks.py43
-rw-r--r--django/contrib/admin/sites.py38
-rw-r--r--docs/ref/checks.txt10
-rw-r--r--tests/admin_checks/tests.py38
5 files changed, 93 insertions, 39 deletions
diff --git a/django/contrib/admin/apps.py b/django/contrib/admin/apps.py
index c965cdbc89..194ec9f89d 100644
--- a/django/contrib/admin/apps.py
+++ b/django/contrib/admin/apps.py
@@ -1,5 +1,5 @@
from django.apps import AppConfig
-from django.contrib.admin.checks import check_admin_app
+from django.contrib.admin.checks import check_admin_app, check_dependencies
from django.core import checks
from django.utils.translation import ugettext_lazy as _
@@ -11,6 +11,7 @@ class SimpleAdminConfig(AppConfig):
verbose_name = _("Administration")
def ready(self):
+ checks.register(check_dependencies, checks.Tags.admin)
checks.register(check_admin_app, checks.Tags.admin)
diff --git a/django/contrib/admin/checks.py b/django/contrib/admin/checks.py
index 60bd236927..48539fe9e5 100644
--- a/django/contrib/admin/checks.py
+++ b/django/contrib/admin/checks.py
@@ -3,6 +3,8 @@ from __future__ import unicode_literals
from itertools import chain
+from django.apps import apps
+from django.conf import settings
from django.contrib.admin.utils import (
NotRelationField, flatten, get_fields_from_path,
)
@@ -12,6 +14,7 @@ from django.db import models
from django.forms.models import (
BaseModelForm, BaseModelFormSet, _get_foreign_key,
)
+from django.template.engine import Engine
def check_admin_app(**kwargs):
@@ -20,6 +23,46 @@ def check_admin_app(**kwargs):
return system_check_errors
+def check_dependencies(**kwargs):
+ """
+ Check that the admin's dependencies are correctly installed.
+ """
+ errors = []
+ # contrib.contenttypes must be installed.
+ if not apps.is_installed('django.contrib.contenttypes'):
+ missing_app = checks.Error(
+ "'django.contrib.contenttypes' must be in INSTALLED_APPS in order "
+ "to use the admin application.",
+ id="admin.E401",
+ )
+ errors.append(missing_app)
+ # The auth context processor must be installed if using the default
+ # authentication backend.
+ try:
+ default_template_engine = Engine.get_default()
+ except Exception:
+ # Skip this non-critical check:
+ # 1. if the user has a non-trivial TEMPLATES setting and Django
+ # can't find a default template engine
+ # 2. if anything goes wrong while loading template engines, in
+ # order to avoid raising an exception from a confusing location
+ # Catching ImproperlyConfigured suffices for 1. but 2. requires
+ # catching all exceptions.
+ pass
+ else:
+ if ('django.contrib.auth.context_processors.auth'
+ not in default_template_engine.context_processors
+ and 'django.contrib.auth.backends.ModelBackend'
+ in settings.AUTHENTICATION_BACKENDS):
+ missing_template = checks.Error(
+ "'django.contrib.auth.context_processors.auth' must be in "
+ "TEMPLATES in order to use the admin application.",
+ id="admin.E402"
+ )
+ errors.append(missing_template)
+ return errors
+
+
class BaseModelAdminChecks(object):
def check(self, admin_obj, **kwargs):
diff --git a/django/contrib/admin/sites.py b/django/contrib/admin/sites.py
index 77da4c0fd7..ba9cbcc135 100644
--- a/django/contrib/admin/sites.py
+++ b/django/contrib/admin/sites.py
@@ -7,7 +7,6 @@ from django.contrib.auth import REDIRECT_FIELD_NAME
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.db.models.base import ModelBase
from django.http import Http404, HttpResponseRedirect
-from django.template.engine import Engine
from django.template.response import TemplateResponse
from django.urls import NoReverseMatch, reverse
from django.utils import six
@@ -172,40 +171,6 @@ class AdminSite(object):
"""
return request.user.is_active and request.user.is_staff
- def check_dependencies(self):
- """
- Check that all things needed to run the admin have been correctly installed.
-
- The default implementation checks that admin and contenttypes apps are
- installed, as well as the auth context processor.
- """
- if not apps.is_installed('django.contrib.admin'):
- raise ImproperlyConfigured(
- "Put 'django.contrib.admin' in your INSTALLED_APPS "
- "setting in order to use the admin application.")
- if not apps.is_installed('django.contrib.contenttypes'):
- raise ImproperlyConfigured(
- "Put 'django.contrib.contenttypes' in your INSTALLED_APPS "
- "setting in order to use the admin application.")
- try:
- default_template_engine = Engine.get_default()
- except Exception:
- # Skip this non-critical check:
- # 1. if the user has a non-trivial TEMPLATES setting and Django
- # can't find a default template engine
- # 2. if anything goes wrong while loading template engines, in
- # order to avoid raising an exception from a confusing location
- # Catching ImproperlyConfigured suffices for 1. but 2. requires
- # catching all exceptions.
- pass
- else:
- if ('django.contrib.auth.context_processors.auth'
- not in default_template_engine.context_processors):
- raise ImproperlyConfigured(
- "Enable 'django.contrib.auth.context_processors.auth' "
- "in your TEMPLATES setting in order to use the admin "
- "application.")
-
def admin_view(self, view, cacheable=False):
"""
Decorator to create an admin view attached to this ``AdminSite``. This
@@ -257,9 +222,6 @@ class AdminSite(object):
# and django.contrib.contenttypes.views imports ContentType.
from django.contrib.contenttypes import views as contenttype_views
- if settings.DEBUG:
- self.check_dependencies()
-
def wrap(view, cacheable=False):
def wrapper(*args, **kwargs):
return self.admin_view(view, cacheable)(*args, **kwargs)
diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt
index e9c8e45cbb..854a9ca254 100644
--- a/docs/ref/checks.txt
+++ b/docs/ref/checks.txt
@@ -409,6 +409,16 @@ registered as an inline on a :class:`~django.contrib.admin.ModelAdmin`.
* **admin.E304**: ``<model>`` has no ``GenericForeignKey`` using content type
field ``<field name>`` and object ID field ``<field name>``.
+AdminSite
+~~~~~~~~~
+
+The following checks are performed on the default
+:class:`~django.contrib.admin.AdminSite`:
+
+* **admin.E401**: :mod:`django.contrib.contenttypes` must be in
+ :setting:`INSTALLED_APPS` in order to use the admin application.
+* **admin.E402**: :mod:`django.contrib.auth.context_processors.auth`
+ must be in :setting:`TEMPLATES` in order to use the admin application.
Auth
----
diff --git a/tests/admin_checks/tests.py b/tests/admin_checks/tests.py
index 280af17e1f..56437c4a49 100644
--- a/tests/admin_checks/tests.py
+++ b/tests/admin_checks/tests.py
@@ -54,6 +54,44 @@ class SystemChecksTestCase(SimpleTestCase):
admin.site.unregister(Song)
admin.sites.system_check_errors = []
+ @override_settings(INSTALLED_APPS=['django.contrib.admin'])
+ def test_contenttypes_dependency(self):
+ errors = admin.checks.check_dependencies()
+ expected = [
+ checks.Error(
+ "'django.contrib.contenttypes' must be in "
+ "INSTALLED_APPS in order to use the admin application.",
+ id="admin.E401",
+ )
+ ]
+ self.assertEqual(errors, expected)
+
+ @override_settings(
+ INSTALLED_APPS=[
+ 'django.contrib.admin',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ ],
+ TEMPLATES=[{
+ 'BACKEND': 'django.template.backends.django.DjangoTemplates',
+ 'DIRS': [],
+ 'APP_DIRS': True,
+ 'OPTIONS': {
+ 'context_processors': [],
+ },
+ }],
+ )
+ def test_auth_contextprocessor_dependency(self):
+ errors = admin.checks.check_dependencies()
+ expected = [
+ checks.Error(
+ "'django.contrib.auth.context_processors.auth' must be in "
+ "TEMPLATES in order to use the admin application.",
+ id="admin.E402",
+ )
+ ]
+ self.assertEqual(errors, expected)
+
@override_settings(DEBUG=True)
def test_custom_adminsite(self):
class CustomAdminSite(admin.AdminSite):