diff --git a/django/contrib/sites/apps.py b/django/contrib/sites/apps.py index c4598049c5..ed52d34786 100644 --- a/django/contrib/sites/apps.py +++ b/django/contrib/sites/apps.py @@ -1,4 +1,6 @@ from django.apps import AppConfig +from django.contrib.sites.checks import check_site_id +from django.core import checks from django.db.models.signals import post_migrate from django.utils.translation import gettext_lazy as _ @@ -11,3 +13,4 @@ class SitesConfig(AppConfig): def ready(self): post_migrate.connect(create_default_site, sender=self) + checks.register(check_site_id, checks.Tags.sites) diff --git a/django/contrib/sites/checks.py b/django/contrib/sites/checks.py new file mode 100644 index 0000000000..c7dfe9ea52 --- /dev/null +++ b/django/contrib/sites/checks.py @@ -0,0 +1,13 @@ +from django.conf import settings +from django.core.checks import Error + + +def check_site_id(app_configs, **kwargs): + if ( + hasattr(settings, 'SITE_ID') and + not isinstance(settings.SITE_ID, (type(None), int)) + ): + return [ + Error('The SITE_ID setting must be an integer', id='sites.E101'), + ] + return [] diff --git a/django/core/checks/registry.py b/django/core/checks/registry.py index c79e3491c4..699bf9ff30 100644 --- a/django/core/checks/registry.py +++ b/django/core/checks/registry.py @@ -15,6 +15,7 @@ class Tags: models = 'models' security = 'security' signals = 'signals' + sites = 'sites' staticfiles = 'staticfiles' templates = 'templates' translation = 'translation' diff --git a/docs/ref/checks.txt b/docs/ref/checks.txt index 97d2c1d097..2f50b2152a 100644 --- a/docs/ref/checks.txt +++ b/docs/ref/checks.txt @@ -85,6 +85,7 @@ Django's system checks are organized using the following tags: * ``models``: Checks of model, field, and manager definitions. * ``security``: Checks security related configuration. * ``signals``: Checks on signal declarations and handler registrations. +* ``sites``: Checks :mod:`django.contrib.sites` configuration. * ``staticfiles``: Checks :mod:`django.contrib.staticfiles` configuration. * ``templates``: Checks template related configuration. * ``translation``: Checks translation related configuration. @@ -101,6 +102,10 @@ Some checks may be registered with multiple tags. The ``database`` checks are now run only for database aliases specified using the :option:`check --database` option. +.. versionchanged:: 3.2 + + The ``sites`` tag was added. + Core system checks ================== @@ -813,6 +818,11 @@ The following checks are performed on any model using a * **sites.E002**: ``CurrentSiteManager`` cannot use ```` as it is not a foreign key or a many-to-many field. +The following checks verify that :mod:`django.contrib.sites` is correctly +configured: + +* **sites.E101**: The :setting:`SITE_ID` setting must be an integer. + ``staticfiles`` --------------- diff --git a/tests/sites_tests/tests.py b/tests/sites_tests/tests.py index 2971a5b853..23a3b5a13f 100644 --- a/tests/sites_tests/tests.py +++ b/tests/sites_tests/tests.py @@ -2,11 +2,13 @@ from django.apps import apps from django.apps.registry import Apps from django.conf import settings from django.contrib.sites import models +from django.contrib.sites.checks import check_site_id from django.contrib.sites.management import create_default_site from django.contrib.sites.middleware import CurrentSiteMiddleware from django.contrib.sites.models import Site, clear_site_cache from django.contrib.sites.requests import RequestSite from django.contrib.sites.shortcuts import get_current_site +from django.core import checks from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.db.models.signals import post_migrate from django.http import HttpRequest, HttpResponse @@ -82,7 +84,7 @@ class SitesFrameworkTests(TestCase): self.assertIsInstance(site, RequestSite) self.assertEqual(site.name, "example.com") - @override_settings(SITE_ID='', ALLOWED_HOSTS=['example.com']) + @override_settings(SITE_ID=None, ALLOWED_HOSTS=['example.com']) def test_get_current_site_no_site_id(self): request = HttpRequest() request.META = { @@ -93,7 +95,7 @@ class SitesFrameworkTests(TestCase): site = get_current_site(request) self.assertEqual(site.name, "example.com") - @override_settings(SITE_ID='', ALLOWED_HOSTS=['example.com']) + @override_settings(SITE_ID=None, ALLOWED_HOSTS=['example.com']) def test_get_current_site_host_with_trailing_dot(self): """ The site is matched if the name in the request has a trailing dot. @@ -106,7 +108,7 @@ class SitesFrameworkTests(TestCase): site = get_current_site(request) self.assertEqual(site.name, 'example.com') - @override_settings(SITE_ID='', ALLOWED_HOSTS=['example.com', 'example.net']) + @override_settings(SITE_ID=None, ALLOWED_HOSTS=['example.com', 'example.net']) def test_get_current_site_no_site_id_and_handle_port_fallback(self): request = HttpRequest() s1 = self.site @@ -167,7 +169,7 @@ class SitesFrameworkTests(TestCase): expected_cache = {self.site.id: self.site} self.assertEqual(models.SITE_CACHE, expected_cache) - with self.settings(SITE_ID=''): + with self.settings(SITE_ID=None): get_current_site(request) expected_cache.update({self.site.domain: self.site}) @@ -176,7 +178,7 @@ class SitesFrameworkTests(TestCase): clear_site_cache(Site, instance=self.site, using='default') self.assertEqual(models.SITE_CACHE, {}) - @override_settings(SITE_ID='', ALLOWED_HOSTS=['example2.com']) + @override_settings(SITE_ID=None, ALLOWED_HOSTS=['example2.com']) def test_clear_site_cache_domain(self): site = Site.objects.create(name='example2.com', domain='example2.com') request = HttpRequest() @@ -205,6 +207,20 @@ class SitesFrameworkTests(TestCase): self.assertEqual(Site.objects.get_by_natural_key(self.site.domain), self.site) self.assertEqual(self.site.natural_key(), (self.site.domain,)) + @override_settings(SITE_ID='1') + def test_check_site_id(self): + self.assertEqual(check_site_id(None), [ + checks.Error( + msg='The SITE_ID setting must be an integer', + id='sites.E101', + ), + ]) + + def test_valid_site_id(self): + for site_id in [1, None]: + with self.subTest(site_id=site_id), self.settings(SITE_ID=site_id): + self.assertEqual(check_site_id(None), []) + @override_settings(ALLOWED_HOSTS=['example.com']) class RequestSiteTests(SimpleTestCase):