diff --git a/pyproject.toml b/pyproject.toml index 20f977d1f..43cd6059e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,7 +42,7 @@ dependencies = [ "django-filter==25.1", "django-formset-js-improved==0.5.0.3", "django-formtools==2.5.1", - "django-hierarkey==1.2.*", + "django-hierarkey==2.0.*", "django-hijack==3.7.*", "django-i18nfield==1.10.*", "django-libsass==0.9", diff --git a/src/pretix/base/migrations/0286_settingsstore_unique.py b/src/pretix/base/migrations/0286_settingsstore_unique.py new file mode 100644 index 000000000..eb93adeac --- /dev/null +++ b/src/pretix/base/migrations/0286_settingsstore_unique.py @@ -0,0 +1,28 @@ +# Generated by Django 4.2.16 on 2025-08-14 09:40 + +from django.db import migrations +from hierarkey.utils import CleanHierarkeyDuplicates + + +class Migration(migrations.Migration): + dependencies = [ + ("pretixbase", "0285_voucher_created"), + ] + + operations = [ + CleanHierarkeyDuplicates("GlobalSettingsObject_SettingsStore"), + CleanHierarkeyDuplicates("Organizer_SettingsStore"), + CleanHierarkeyDuplicates("Event_SettingsStore"), + migrations.AlterUniqueTogether( + name="event_settingsstore", + unique_together={("object", "key")}, + ), + migrations.AlterUniqueTogether( + name="globalsettingsobject_settingsstore", + unique_together={("key",)}, + ), + migrations.AlterUniqueTogether( + name="organizer_settingsstore", + unique_together={("object", "key")}, + ), + ] diff --git a/src/pretix/base/models/event.py b/src/pretix/base/models/event.py index 7f28f2e97..c5b5061f8 100644 --- a/src/pretix/base/models/event.py +++ b/src/pretix/base/models/event.py @@ -1085,7 +1085,7 @@ class Event(EventMixin, LoggedModel): s.save(force_insert=True) valid_sales_channel_identifers = set(self.organizer.sales_channels.values_list("identifier", flat=True)) - skip_settings = ( + skip_settings = { 'ticket_secrets_pretix_sig1_pubkey', 'ticket_secrets_pretix_sig1_privkey', # no longer used, but we still don't need to copy them @@ -1093,7 +1093,10 @@ class Event(EventMixin, LoggedModel): 'presale_css_checksum', 'presale_widget_css_file', 'presale_widget_css_checksum', - ) + } | { + # Some settings might already exist due to e.g. the timezone being special in the API + s.key for s in self.settings._objects.all() + } settings_to_save = [] for s in other.settings._objects.all(): if s.key in skip_settings: