From 064df36910ba6f79adf447764a0f2c6051a7025f Mon Sep 17 00:00:00 2001 From: Sidney Richards Date: Thu, 19 Dec 2024 19:52:12 +0100 Subject: [PATCH] [#42] Handle Site creation in SitesConfigurationStep when no Sites models --- .../contrib/sites/steps.py | 19 +++++++-- tests/sites/test_sites_configuration_step.py | 42 +++++++++++++++++++ 2 files changed, 58 insertions(+), 3 deletions(-) diff --git a/django_setup_configuration/contrib/sites/steps.py b/django_setup_configuration/contrib/sites/steps.py index 2aff713..da100f9 100644 --- a/django_setup_configuration/contrib/sites/steps.py +++ b/django_setup_configuration/contrib/sites/steps.py @@ -1,5 +1,6 @@ +from django.conf import settings from django.contrib.sites.models import Site -from django.core.exceptions import ValidationError +from django.core.exceptions import ImproperlyConfigured, ValidationError from django.db import IntegrityError from django_setup_configuration.configuration import BaseConfigurationStep @@ -18,11 +19,23 @@ def execute(self, model: SitesConfigurationModel) -> None: if not model.items: raise ConfigurationRunFailed("Please specify one or more sites") - # We need to ensure the current site is updated, to make sure that `get_current` - # keeps working first_site = model.items[0] + + # We need to ensure the current site is updated, to make sure that `get_current` + # keeps working. The first site in the list is treated as the current site. + current_site = None + try: current_site = Site.objects.get_current() + except (Site.DoesNotExist, ImproperlyConfigured): + current_site = Site() + + # We have no current site, which means there is no site pointed to by + # settings.SITE_ID -- however, `get_current()` expects a Site with that ID + # to exist, so we have to make sure the created site receives that ID. + current_site.pk = getattr(settings, "SITE_ID") + + try: current_site.domain = first_site.domain current_site.name = first_site.name current_site.full_clean(exclude=("id",), validate_unique=False) diff --git a/tests/sites/test_sites_configuration_step.py b/tests/sites/test_sites_configuration_step.py index ac8ae7d..c062651 100644 --- a/tests/sites/test_sites_configuration_step.py +++ b/tests/sites/test_sites_configuration_step.py @@ -1,4 +1,5 @@ from django.contrib.sites.models import Site +from django.core.exceptions import ImproperlyConfigured import pytest @@ -82,3 +83,44 @@ def test_execute_configuration_step_failing_should_keep_existing_sites(): assert Site.objects.count() == 1 assert Site.objects.get() == site + + +@pytest.mark.django_db +def test_execute_configuration_step_creates_a_current_site_if_no_sites_exist(): + Site.objects.all().delete() + + execute_single_step(SitesConfigurationStep, yaml_source=CONFIG_FILE_PATH) + + site1, site2 = Site.objects.all() + + assert site1.domain == "domain.local1:8000" + assert site1.name == "Domain1" + assert site2.domain == "domain.local2:8000" + assert site2.name == "Domain2" + assert Site.objects.get_current() == site1 + + +@pytest.fixture() +def empty_site_id_in_settings(settings): + settings.SITE_ID = None + + +@pytest.mark.usefixtures("empty_site_id_in_settings") +@pytest.mark.django_db +def test_execute_configuration_step_creates_a_current_site_if_no_sites_or_site_id(): + Site.objects.all().delete() + + execute_single_step(SitesConfigurationStep, yaml_source=CONFIG_FILE_PATH) + + site1, site2 = Site.objects.all() + + assert site1.domain == "domain.local1:8000" + assert site1.name == "Domain1" + assert site2.domain == "domain.local2:8000" + assert site2.name == "Domain2" + + # There is no SITE_ID defined. We should still have created the Sites, but there is + # no default defined, so `get_current()` will not work without passing a request + # (which would allow Django to match on the host). + with pytest.raises(ImproperlyConfigured): + Site.objects.get_current()