Fixed #24116 -- Moved AdminSite.check_dependencies() to system checks.

This commit is contained in:
Vincenzo Pandolfo 2015-12-10 12:45:21 +00:00 committed by Tim Graham
parent 956cde8004
commit 0490d72f2a
5 changed files with 93 additions and 39 deletions

View File

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

View File

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

View File

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

View File

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

View File

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