From 4c948c7c9d8b8bb4a36f703a6e96de5914740b0f Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Thu, 12 Feb 2015 13:58:37 -0500 Subject: [PATCH] [1.8.x] Fixed #24332 -- Fixed contrib.sites create_default_site() when 'default' DATABASES is empty. Backport of e8cf4f8abec87b9da6ed8e5c8cf833af9b27f4dd from master --- django/contrib/sites/management.py | 2 +- django/contrib/sites/models.py | 3 ++- docs/releases/1.7.5.txt | 3 +++ tests/sites_tests/tests.py | 30 ++++++++++++++++++++++++++++-- 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/django/contrib/sites/management.py b/django/contrib/sites/management.py index 33bd44dfdc..7c6c32d95b 100644 --- a/django/contrib/sites/management.py +++ b/django/contrib/sites/management.py @@ -17,7 +17,7 @@ def create_default_site(app_config, verbosity=2, interactive=True, using=DEFAULT if not router.allow_migrate(using, Site): return - if not Site.objects.exists(): + if not Site.objects.using(using).exists(): # The default settings set SITE_ID = 1, and some tests in Django's test # suite rely on this value. However, if database sequences are reused # (e.g. in the test suite after flush/syncdb), it isn't guaranteed that diff --git a/django/contrib/sites/models.py b/django/contrib/sites/models.py index 150cfa6d18..7662145ac5 100644 --- a/django/contrib/sites/models.py +++ b/django/contrib/sites/models.py @@ -112,12 +112,13 @@ def clear_site_cache(sender, **kwargs): Clears the cache (if primed) each time a site is saved or deleted """ instance = kwargs['instance'] + using = kwargs['using'] try: del SITE_CACHE[instance.pk] except KeyError: pass try: - del SITE_CACHE[Site.objects.get(pk=instance.pk).domain] + del SITE_CACHE[Site.objects.using(using).get(pk=instance.pk).domain] except (KeyError, Site.DoesNotExist): pass pre_save.connect(clear_site_cache, sender=Site) diff --git a/docs/releases/1.7.5.txt b/docs/releases/1.7.5.txt index afce510aae..604cf9146a 100644 --- a/docs/releases/1.7.5.txt +++ b/docs/releases/1.7.5.txt @@ -16,3 +16,6 @@ Bugfixes * Fixed a regression that prevented custom fields inheriting from ``ManyToManyField`` from being recognized in migrations (:ticket:`24236`). + +* Fixed crash in ``contrib.sites`` migrations when a default database isn't + used (:ticket:`24332`). diff --git a/tests/sites_tests/tests.py b/tests/sites_tests/tests.py index eeb6a44646..7eb1c20b60 100644 --- a/tests/sites_tests/tests.py +++ b/tests/sites_tests/tests.py @@ -17,6 +17,7 @@ from django.test.utils import captured_stdout @modify_settings(INSTALLED_APPS={'append': 'django.contrib.sites'}) class SitesFrameworkTests(TestCase): + multi_db = True def setUp(self): self.site = Site( @@ -112,7 +113,26 @@ class SitesFrameworkTests(TestCase): expected_cache.update({self.site.domain: self.site}) self.assertEqual(models.SITE_CACHE, expected_cache) - clear_site_cache(Site, instance=self.site) + clear_site_cache(Site, instance=self.site, using='default') + self.assertEqual(models.SITE_CACHE, {}) + + @override_settings(SITE_ID='') + def test_clear_site_cache_domain(self): + site = Site.objects.create(name='example2.com', domain='example2.com') + request = HttpRequest() + request.META = { + "SERVER_NAME": "example2.com", + "SERVER_PORT": "80", + } + get_current_site(request) # prime the models.SITE_CACHE + expected_cache = {site.domain: site} + self.assertEqual(models.SITE_CACHE, expected_cache) + + # Site exists in 'default' database so using='other' shouldn't clear. + clear_site_cache(Site, instance=site, using='other') + self.assertEqual(models.SITE_CACHE, expected_cache) + # using='default' should clear. + clear_site_cache(Site, instance=site, using='default') self.assertEqual(models.SITE_CACHE, {}) @@ -146,7 +166,7 @@ class CreateDefaultSiteTests(TestCase): self.assertEqual("", stdout.getvalue()) @override_settings(DATABASE_ROUTERS=[JustOtherRouter()]) - def test_multi_db(self): + def test_multi_db_with_router(self): """ #16353, #16828 - The default site creation should respect db routing. """ @@ -155,6 +175,12 @@ class CreateDefaultSiteTests(TestCase): self.assertFalse(Site.objects.using('default').exists()) self.assertTrue(Site.objects.using('other').exists()) + def test_multi_db(self): + create_default_site(self.app_config, using='default', verbosity=0) + create_default_site(self.app_config, using='other', verbosity=0) + self.assertTrue(Site.objects.using('default').exists()) + self.assertTrue(Site.objects.using('other').exists()) + def test_save_another(self): """ #17415 - Another site can be created right after the default one.