diff --git a/src/pretix/control/views/event.py b/src/pretix/control/views/event.py index 9c9165511..4cc35964f 100644 --- a/src/pretix/control/views/event.py +++ b/src/pretix/control/views/event.py @@ -42,6 +42,7 @@ from itertools import groupby from urllib.parse import urlsplit import bleach +from django.apps import apps from django.conf import settings from django.contrib import messages from django.contrib.contenttypes.models import ContentType @@ -1025,9 +1026,27 @@ class EventDelete(RecentAuthenticationRequiredMixin, EventPermissionRequiredMixi self.request.event.delete() messages.success(self.request, _('The event has been deleted.')) return redirect(self.get_success_url()) - except ProtectedError: - messages.error(self.request, _('The event could not be deleted as some constraints (e.g. data created by ' - 'plug-ins) do not allow it.')) + except ProtectedError as e: + err = gettext('The event could not be deleted as some constraints (e.g. data created by plug-ins) do not allow it.') + + app_labels = set() + for e in e.protected_objects: + app_labels.add(type(e)._meta.app_label) + + plugin_names = [] + for app_label in app_labels: + app = apps.get_app_config(app_label) + if hasattr(app, 'PretixPluginMeta'): + plugin_names.append(str(app.PretixPluginMeta.name)) + else: + plugin_names.append(str(app.verbose_name)) + + if plugin_names: + err += ' ' + gettext( + 'Specifically, the following plugins still contain data depends on this event: {plugin_names}' + ).format(plugin_names=', '.join(plugin_names)) + + messages.error(self.request, err) return self.get(self.request, *self.args, **self.kwargs) def get_success_url(self) -> str: diff --git a/src/pretix/control/views/organizer.py b/src/pretix/control/views/organizer.py index 908e4dfd3..a9be06d84 100644 --- a/src/pretix/control/views/organizer.py +++ b/src/pretix/control/views/organizer.py @@ -393,9 +393,23 @@ class OrganizerDelete(AdministratorPermissionRequiredMixin, FormView): self.request.organizer.delete() messages.success(self.request, _('The organizer has been deleted.')) return redirect(self.get_success_url()) - except ProtectedError: - messages.error(self.request, _('The organizer could not be deleted as some constraints (e.g. data created by ' - 'plug-ins) do not allow it.')) + except ProtectedError as e: + err = gettext('The organizer could not be deleted as some constraints (e.g. data created by plug-ins) do not allow it.') + + # Unlike deleting events (which is done by regular backend users), this feature can only be used by sysadmins, + # so we expose more technical / less polished information. + affected_models = set() + for m in e.protected_objects: + affected_models.add(type(m)._meta.label) + + if affected_models: + err += ' ' + gettext( + 'The following database models still contain data that cannot be deleted automatically: {affected_models}' + ).format( + affected_models=', '.join(list(affected_models)) + ) + + messages.error(self.request, err) return self.get(self.request, *self.args, **self.kwargs) def get_success_url(self) -> str: