Fixed #24116 -- Moved AdminSite.check_dependencies() to system checks.
This commit is contained in:
parent
956cde8004
commit
0490d72f2a
|
@ -1,5 +1,5 @@
|
||||||
from django.apps import AppConfig
|
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.core import checks
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ class SimpleAdminConfig(AppConfig):
|
||||||
verbose_name = _("Administration")
|
verbose_name = _("Administration")
|
||||||
|
|
||||||
def ready(self):
|
def ready(self):
|
||||||
|
checks.register(check_dependencies, checks.Tags.admin)
|
||||||
checks.register(check_admin_app, checks.Tags.admin)
|
checks.register(check_admin_app, checks.Tags.admin)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@ from __future__ import unicode_literals
|
||||||
|
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
|
|
||||||
|
from django.apps import apps
|
||||||
|
from django.conf import settings
|
||||||
from django.contrib.admin.utils import (
|
from django.contrib.admin.utils import (
|
||||||
NotRelationField, flatten, get_fields_from_path,
|
NotRelationField, flatten, get_fields_from_path,
|
||||||
)
|
)
|
||||||
|
@ -12,6 +14,7 @@ from django.db import models
|
||||||
from django.forms.models import (
|
from django.forms.models import (
|
||||||
BaseModelForm, BaseModelFormSet, _get_foreign_key,
|
BaseModelForm, BaseModelFormSet, _get_foreign_key,
|
||||||
)
|
)
|
||||||
|
from django.template.engine import Engine
|
||||||
|
|
||||||
|
|
||||||
def check_admin_app(**kwargs):
|
def check_admin_app(**kwargs):
|
||||||
|
@ -20,6 +23,46 @@ def check_admin_app(**kwargs):
|
||||||
return system_check_errors
|
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):
|
class BaseModelAdminChecks(object):
|
||||||
|
|
||||||
def check(self, admin_obj, **kwargs):
|
def check(self, admin_obj, **kwargs):
|
||||||
|
|
|
@ -7,7 +7,6 @@ from django.contrib.auth import REDIRECT_FIELD_NAME
|
||||||
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
|
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
|
||||||
from django.db.models.base import ModelBase
|
from django.db.models.base import ModelBase
|
||||||
from django.http import Http404, HttpResponseRedirect
|
from django.http import Http404, HttpResponseRedirect
|
||||||
from django.template.engine import Engine
|
|
||||||
from django.template.response import TemplateResponse
|
from django.template.response import TemplateResponse
|
||||||
from django.urls import NoReverseMatch, reverse
|
from django.urls import NoReverseMatch, reverse
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
@ -172,40 +171,6 @@ class AdminSite(object):
|
||||||
"""
|
"""
|
||||||
return request.user.is_active and request.user.is_staff
|
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):
|
def admin_view(self, view, cacheable=False):
|
||||||
"""
|
"""
|
||||||
Decorator to create an admin view attached to this ``AdminSite``. This
|
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.
|
# and django.contrib.contenttypes.views imports ContentType.
|
||||||
from django.contrib.contenttypes import views as contenttype_views
|
from django.contrib.contenttypes import views as contenttype_views
|
||||||
|
|
||||||
if settings.DEBUG:
|
|
||||||
self.check_dependencies()
|
|
||||||
|
|
||||||
def wrap(view, cacheable=False):
|
def wrap(view, cacheable=False):
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
return self.admin_view(view, cacheable)(*args, **kwargs)
|
return self.admin_view(view, cacheable)(*args, **kwargs)
|
||||||
|
|
|
@ -409,6 +409,16 @@ registered as an inline on a :class:`~django.contrib.admin.ModelAdmin`.
|
||||||
* **admin.E304**: ``<model>`` has no ``GenericForeignKey`` using content type
|
* **admin.E304**: ``<model>`` has no ``GenericForeignKey`` using content type
|
||||||
field ``<field name>`` and object ID field ``<field name>``.
|
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
|
Auth
|
||||||
----
|
----
|
||||||
|
|
|
@ -54,6 +54,44 @@ class SystemChecksTestCase(SimpleTestCase):
|
||||||
admin.site.unregister(Song)
|
admin.site.unregister(Song)
|
||||||
admin.sites.system_check_errors = []
|
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)
|
@override_settings(DEBUG=True)
|
||||||
def test_custom_adminsite(self):
|
def test_custom_adminsite(self):
|
||||||
class CustomAdminSite(admin.AdminSite):
|
class CustomAdminSite(admin.AdminSite):
|
||||||
|
|
Loading…
Reference in New Issue