From 433262f6fce8254cd77e1669ab511f8a0f233847 Mon Sep 17 00:00:00 2001 From: Raphael Michel Date: Tue, 24 Jan 2023 14:16:01 +0100 Subject: [PATCH] Prepare for DeleteView change in Django 4.0 --- src/pretix/control/views/checkin.py | 5 ++-- src/pretix/control/views/discounts.py | 4 +-- src/pretix/control/views/event.py | 5 ++-- src/pretix/control/views/item.py | 11 ++++---- src/pretix/control/views/oauth.py | 3 +++ src/pretix/control/views/orders.py | 5 ++-- src/pretix/control/views/organizer.py | 15 ++++++----- src/pretix/control/views/subevents.py | 7 +++-- src/pretix/control/views/vouchers.py | 7 ++--- src/pretix/control/views/waitinglist.py | 4 +-- src/pretix/helpers/compat.py | 30 +++++++++++++++++++++ src/pretix/plugins/badges/views.py | 5 ++-- src/pretix/plugins/ticketoutputpdf/views.py | 5 ++-- src/pretix/presale/views/customer.py | 7 ++--- 14 files changed, 76 insertions(+), 37 deletions(-) diff --git a/src/pretix/control/views/checkin.py b/src/pretix/control/views/checkin.py index 6b26651249..b481c6b2dc 100644 --- a/src/pretix/control/views/checkin.py +++ b/src/pretix/control/views/checkin.py @@ -43,7 +43,7 @@ from django.urls import reverse from django.utils.functional import cached_property from django.utils.timezone import is_aware, make_aware, now from django.utils.translation import gettext_lazy as _ -from django.views.generic import DeleteView, ListView +from django.views.generic import ListView from pytz import UTC from pretix.base.channels import get_all_sales_channels @@ -57,6 +57,7 @@ from pretix.control.forms.filter import ( ) from pretix.control.permissions import EventPermissionRequiredMixin from pretix.control.views import CreateView, PaginationMixin, UpdateView +from pretix.helpers.compat import CompatDeleteView from pretix.helpers.models import modelcopy @@ -394,7 +395,7 @@ class CheckinListUpdate(EventPermissionRequiredMixin, UpdateView): return super().form_invalid(form) -class CheckinListDelete(EventPermissionRequiredMixin, DeleteView): +class CheckinListDelete(EventPermissionRequiredMixin, CompatDeleteView): model = CheckinList template_name = 'pretixcontrol/checkin/list_delete.html' permission = 'can_change_event_settings' diff --git a/src/pretix/control/views/discounts.py b/src/pretix/control/views/discounts.py index c0002519ec..cb028d6f69 100644 --- a/src/pretix/control/views/discounts.py +++ b/src/pretix/control/views/discounts.py @@ -35,7 +35,6 @@ from django.utils.functional import cached_property from django.utils.translation import gettext_lazy as _ from django.views.decorators.http import require_http_methods from django.views.generic import ListView -from django.views.generic.edit import DeleteView from pretix.base.models import CartPosition, Discount from pretix.control.forms.discounts import DiscountForm @@ -45,10 +44,11 @@ from pretix.control.permissions import ( from pretix.helpers.models import modelcopy from ...base.channels import get_all_sales_channels +from ...helpers.compat import CompatDeleteView from . import CreateView, PaginationMixin, UpdateView -class DiscountDelete(EventPermissionRequiredMixin, DeleteView): +class DiscountDelete(EventPermissionRequiredMixin, CompatDeleteView): model = Discount template_name = 'pretixcontrol/items/discount_delete.html' permission = 'can_change_items' diff --git a/src/pretix/control/views/event.py b/src/pretix/control/views/event.py index 377e6b3247..9c9165511b 100644 --- a/src/pretix/control/views/event.py +++ b/src/pretix/control/views/event.py @@ -58,7 +58,7 @@ from django.urls import reverse from django.utils.functional import cached_property from django.utils.timezone import now from django.utils.translation import gettext, gettext_lazy as _ -from django.views.generic import DeleteView, FormView, ListView +from django.views.generic import FormView, ListView from django.views.generic.base import TemplateView, View from django.views.generic.detail import SingleObjectMixin from i18nfield.strings import LazyI18nString @@ -94,6 +94,7 @@ from ...base.models.items import ( Item, ItemCategory, ItemMetaProperty, Question, Quota, ) from ...base.settings import SETTINGS_AFFECTING_CSS, LazyI18nStringList +from ...helpers.compat import CompatDeleteView from ...helpers.format import format_map from ..logdisplay import OVERVIEW_BANLIST from . import CreateView, PaginationMixin, UpdateView @@ -1243,7 +1244,7 @@ class TaxUpdate(EventSettingsViewMixin, EventPermissionRequiredMixin, UpdateView return super().form_invalid(form) -class TaxDelete(EventSettingsViewMixin, EventPermissionRequiredMixin, DeleteView): +class TaxDelete(EventSettingsViewMixin, EventPermissionRequiredMixin, CompatDeleteView): model = TaxRule template_name = 'pretixcontrol/event/tax_delete.html' permission = 'can_change_event_settings' diff --git a/src/pretix/control/views/item.py b/src/pretix/control/views/item.py index cd1c95527c..b6540d1251 100644 --- a/src/pretix/control/views/item.py +++ b/src/pretix/control/views/item.py @@ -56,7 +56,6 @@ from django.utils.translation import gettext, gettext_lazy as _ from django.views.decorators.http import require_http_methods from django.views.generic import ListView from django.views.generic.detail import DetailView, SingleObjectMixin -from django.views.generic.edit import DeleteView from django_countries.fields import Country from pretix.api.serializers.item import ( @@ -85,6 +84,7 @@ from pretix.control.signals import item_forms, item_formsets from pretix.helpers.models import modelcopy from ...base.channels import get_all_sales_channels +from ...helpers.compat import CompatDeleteView from . import ChartContainingView, CreateView, PaginationMixin, UpdateView @@ -189,9 +189,8 @@ def reorder_items(request, organizer, event): return HttpResponse() -class CategoryDelete(EventPermissionRequiredMixin, DeleteView): +class CategoryDelete(EventPermissionRequiredMixin, CompatDeleteView): model = ItemCategory - form_class = CategoryForm template_name = 'pretixcontrol/items/category_delete.html' permission = 'can_change_items' context_object_name = 'category' @@ -523,7 +522,7 @@ def reorder_questions(request, organizer, event): return HttpResponse() -class QuestionDelete(EventPermissionRequiredMixin, DeleteView): +class QuestionDelete(EventPermissionRequiredMixin, CompatDeleteView): model = Question template_name = 'pretixcontrol/items/question_delete.html' permission = 'can_change_items' @@ -1090,7 +1089,7 @@ class QuotaUpdate(EventPermissionRequiredMixin, UpdateView): return super().form_invalid(form) -class QuotaDelete(EventPermissionRequiredMixin, DeleteView): +class QuotaDelete(EventPermissionRequiredMixin, CompatDeleteView): model = Quota template_name = 'pretixcontrol/items/quota_delete.html' permission = 'can_change_items' @@ -1464,7 +1463,7 @@ class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, MetaDataE return f -class ItemDelete(EventPermissionRequiredMixin, DeleteView): +class ItemDelete(EventPermissionRequiredMixin, CompatDeleteView): model = Item template_name = 'pretixcontrol/item/delete.html' permission = 'can_change_items' diff --git a/src/pretix/control/views/oauth.py b/src/pretix/control/views/oauth.py index 9e5a091060..4767d0e006 100644 --- a/src/pretix/control/views/oauth.py +++ b/src/pretix/control/views/oauth.py @@ -127,6 +127,9 @@ class OAuthApplicationDeleteView(ApplicationDelete): self.object.save() return HttpResponseRedirect(self.success_url) + def form_valid(self, form): + return self.delete(self.request, self.args, self.kwargs) + class AuthorizationListView(ListView): template_name = 'pretixcontrol/oauth/authorized.html' diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py index e6e1241b7e..594a5509fc 100644 --- a/src/pretix/control/views/orders.py +++ b/src/pretix/control/views/orders.py @@ -66,7 +66,7 @@ from django.utils.http import url_has_allowed_host_and_scheme from django.utils.timezone import make_aware, now from django.utils.translation import gettext, gettext_lazy as _, ngettext from django.views.generic import ( - DeleteView, DetailView, FormView, ListView, TemplateView, View, + DetailView, FormView, ListView, TemplateView, View, ) from i18nfield.strings import LazyI18nString @@ -127,6 +127,7 @@ from pretix.control.forms.rrule import RRuleForm from pretix.control.permissions import EventPermissionRequiredMixin from pretix.control.signals import order_search_forms from pretix.control.views import PaginationMixin +from pretix.helpers.compat import CompatDeleteView from pretix.helpers.format import format_map from pretix.helpers.safedownload import check_token from pretix.presale.signals import question_form_fields @@ -2453,7 +2454,7 @@ class ExportView(EventPermissionRequiredMixin, ExportMixin, ListView): return ctx -class DeleteScheduledExportView(EventPermissionRequiredMixin, ExportMixin, DeleteView): +class DeleteScheduledExportView(EventPermissionRequiredMixin, ExportMixin, CompatDeleteView): permission = 'can_view_orders' template_name = 'pretixcontrol/orders/export_delete.html' context_object_name = 'export' diff --git a/src/pretix/control/views/organizer.py b/src/pretix/control/views/organizer.py index c8d87e15b4..b10cd442bc 100644 --- a/src/pretix/control/views/organizer.py +++ b/src/pretix/control/views/organizer.py @@ -111,6 +111,7 @@ from pretix.control.signals import nav_organizer from pretix.control.views import PaginationMixin from pretix.control.views.mailsetup import MailSettingsSetupView from pretix.helpers import GroupConcat +from pretix.helpers.compat import CompatDeleteView from pretix.helpers.dicts import merge_dicts from pretix.helpers.format import format_map from pretix.helpers.urls import build_absolute_uri as build_global_uri @@ -626,7 +627,7 @@ class TeamUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, return super().form_invalid(form) -class TeamDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DeleteView): +class TeamDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CompatDeleteView): model = Team template_name = 'pretixcontrol/organizers/team_delete.html' permission = 'can_change_teams' @@ -1893,7 +1894,7 @@ class GateUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, return super().form_invalid(form) -class GateDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DeleteView): +class GateDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CompatDeleteView): model = Gate template_name = 'pretixcontrol/organizers/gate_delete.html' permission = 'can_change_organizer_settings' @@ -1984,7 +1985,7 @@ class EventMetaPropertyUpdateView(OrganizerDetailViewMixin, OrganizerPermissionR return super().form_invalid(form) -class EventMetaPropertyDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DeleteView): +class EventMetaPropertyDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CompatDeleteView): model = EventMetaProperty template_name = 'pretixcontrol/organizers/property_delete.html' permission = 'can_change_organizer_settings' @@ -2107,7 +2108,7 @@ class MembershipTypeUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequ return super().form_invalid(form) -class MembershipTypeDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DeleteView): +class MembershipTypeDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CompatDeleteView): model = MembershipType template_name = 'pretixcontrol/organizers/membershiptype_delete.html' permission = 'can_change_organizer_settings' @@ -2220,7 +2221,7 @@ class SSOProviderUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequire return super().form_invalid(form) -class SSOProviderDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DeleteView): +class SSOProviderDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CompatDeleteView): model = CustomerSSOProvider template_name = 'pretixcontrol/organizers/ssoprovider_delete.html' permission = 'can_change_organizer_settings' @@ -2348,7 +2349,7 @@ class SSOClientUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequiredM return super().form_invalid(form) -class SSOClientDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DeleteView): +class SSOClientDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CompatDeleteView): model = CustomerSSOClient template_name = 'pretixcontrol/organizers/ssoclient_delete.html' permission = 'can_change_organizer_settings' @@ -2611,7 +2612,7 @@ class MembershipUpdateView(OrganizerDetailViewMixin, OrganizerPermissionRequired }) -class MembershipDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, DeleteView): +class MembershipDeleteView(OrganizerDetailViewMixin, OrganizerPermissionRequiredMixin, CompatDeleteView): template_name = 'pretixcontrol/organizers/customer_membership_delete.html' permission = 'can_manage_customers' context_object_name = 'membership' diff --git a/src/pretix/control/views/subevents.py b/src/pretix/control/views/subevents.py index 5652d79979..5ad3089b19 100644 --- a/src/pretix/control/views/subevents.py +++ b/src/pretix/control/views/subevents.py @@ -52,9 +52,7 @@ from django.utils.functional import cached_property from django.utils.timezone import make_aware from django.utils.translation import gettext_lazy as _, pgettext_lazy from django.views import View -from django.views.generic import ( - CreateView, DeleteView, FormView, ListView, UpdateView, -) +from django.views.generic import CreateView, FormView, ListView, UpdateView from pretix.base.models import CartPosition, LogEntry from pretix.base.models.checkin import CheckinList @@ -80,6 +78,7 @@ from pretix.control.signals import subevent_forms from pretix.control.views import PaginationMixin from pretix.control.views.event import MetaDataEditorMixin from pretix.helpers import GroupConcat +from pretix.helpers.compat import CompatDeleteView from pretix.helpers.models import modelcopy @@ -148,7 +147,7 @@ class SubEventList(EventPermissionRequiredMixin, PaginationMixin, SubEventQueryM return ctx -class SubEventDelete(EventPermissionRequiredMixin, DeleteView): +class SubEventDelete(EventPermissionRequiredMixin, CompatDeleteView): model = SubEvent template_name = 'pretixcontrol/subevents/delete.html' permission = 'can_change_settings' diff --git a/src/pretix/control/views/vouchers.py b/src/pretix/control/views/vouchers.py index 05978217b7..1dfe86f6a0 100644 --- a/src/pretix/control/views/vouchers.py +++ b/src/pretix/control/views/vouchers.py @@ -53,7 +53,7 @@ from django.utils.safestring import mark_safe from django.utils.timezone import now from django.utils.translation import gettext_lazy as _ from django.views.generic import ( - CreateView, DeleteView, ListView, TemplateView, UpdateView, View, + CreateView, ListView, TemplateView, UpdateView, View, ) from pretix.base.models import CartPosition, LogEntry, Voucher @@ -66,6 +66,7 @@ from pretix.control.forms.vouchers import VoucherBulkForm, VoucherForm from pretix.control.permissions import EventPermissionRequiredMixin from pretix.control.signals import voucher_form_class from pretix.control.views import PaginationMixin +from pretix.helpers.compat import CompatDeleteView from pretix.helpers.models import modelcopy @@ -182,7 +183,7 @@ class VoucherTags(EventPermissionRequiredMixin, TemplateView): return VoucherTagFilterForm(data=self.request.GET, event=self.request.event) -class VoucherDeleteCarts(EventPermissionRequiredMixin, DeleteView): +class VoucherDeleteCarts(EventPermissionRequiredMixin, CompatDeleteView): model = Voucher template_name = 'pretixcontrol/vouchers/delete_carts.html' permission = 'can_change_vouchers' @@ -214,7 +215,7 @@ class VoucherDeleteCarts(EventPermissionRequiredMixin, DeleteView): }) -class VoucherDelete(EventPermissionRequiredMixin, DeleteView): +class VoucherDelete(EventPermissionRequiredMixin, CompatDeleteView): model = Voucher template_name = 'pretixcontrol/vouchers/delete.html' permission = 'can_change_vouchers' diff --git a/src/pretix/control/views/waitinglist.py b/src/pretix/control/views/waitinglist.py index ee775665cb..00a96d6544 100644 --- a/src/pretix/control/views/waitinglist.py +++ b/src/pretix/control/views/waitinglist.py @@ -48,7 +48,6 @@ from django.utils.timezone import now from django.utils.translation import gettext_lazy as _, pgettext from django.views import View from django.views.generic import ListView -from django.views.generic.edit import DeleteView from pretix.base.models import Item, Quota, WaitingListEntry from pretix.base.models.waitinglist import WaitingListException @@ -58,6 +57,7 @@ from pretix.control.forms.waitinglist import WaitingListEntryTransferForm from pretix.control.permissions import EventPermissionRequiredMixin from pretix.control.views import PaginationMixin +from ...helpers.compat import CompatDeleteView from . import UpdateView @@ -338,7 +338,7 @@ class WaitingListView(EventPermissionRequiredMixin, WaitingListQuerySetMixin, Pa return '{}_waitinglist'.format(self.request.event.slug) -class EntryDelete(EventPermissionRequiredMixin, DeleteView): +class EntryDelete(EventPermissionRequiredMixin, CompatDeleteView): model = WaitingListEntry template_name = 'pretixcontrol/waitinglist/delete.html' permission = 'can_change_orders' diff --git a/src/pretix/helpers/compat.py b/src/pretix/helpers/compat.py index a0312ec448..5b75a4a026 100644 --- a/src/pretix/helpers/compat.py +++ b/src/pretix/helpers/compat.py @@ -22,9 +22,39 @@ import datetime import sys +from django.forms import Form +from django.views.generic.detail import ( + BaseDetailView, SingleObjectTemplateResponseMixin, +) +from django.views.generic.edit import DeletionMixin, FormMixin + def date_fromisocalendar(isoyear, isoweek, isoday): if sys.version_info < (3, 8): return datetime.datetime.strptime(f'{isoyear}-W{isoweek}-{isoday}', "%G-W%V-%u") else: return datetime.datetime.fromisocalendar(isoyear, isoweek, isoday) + + +class CompatDeleteView(SingleObjectTemplateResponseMixin, DeletionMixin, FormMixin, BaseDetailView): + """ + This is a DeleteView variant that allows us to create subclasses that work on both Django 3.2 and + Django 4.0. + """ + form_class = Form + template_name_suffix = "_confirm_delete" + + def post(self, request, *args, **kwargs): + # Set self.object before the usual form processing flow. + # Inlined because having DeletionMixin as the first base, for + # get_success_url(), makes leveraging super() with ProcessFormView + # overly complex. + self.object = self.get_object() + form = self.get_form() + if form.is_valid(): + return self.form_valid(form) + else: + return self.form_invalid(form) + + def form_valid(self, form): + return self.delete(self.request, self.args, self.kwargs) diff --git a/src/pretix/plugins/badges/views.py b/src/pretix/plugins/badges/views.py index 3f1fada646..3e4dea19d1 100644 --- a/src/pretix/plugins/badges/views.py +++ b/src/pretix/plugins/badges/views.py @@ -36,7 +36,7 @@ from django.utils.functional import cached_property from django.utils.timezone import now from django.utils.translation import gettext_lazy as _ from django.views import View -from django.views.generic import CreateView, DeleteView, DetailView, ListView +from django.views.generic import CreateView, DetailView, ListView from reportlab.lib import pagesizes from reportlab.pdfgen import canvas @@ -49,6 +49,7 @@ from pretix.helpers.models import modelcopy from pretix.plugins.badges.forms import BadgeLayoutForm from pretix.plugins.badges.tasks import badges_create_pdf +from ...helpers.compat import CompatDeleteView from .models import BadgeLayout @@ -142,7 +143,7 @@ class LayoutSetDefault(EventPermissionRequiredMixin, DetailView): }) -class LayoutDelete(EventPermissionRequiredMixin, DeleteView): +class LayoutDelete(EventPermissionRequiredMixin, CompatDeleteView): model = BadgeLayout template_name = 'pretixplugins/badges/delete.html' permission = 'can_change_event_settings' diff --git a/src/pretix/plugins/ticketoutputpdf/views.py b/src/pretix/plugins/ticketoutputpdf/views.py index 6bc4bf6bca..368eba1caf 100644 --- a/src/pretix/plugins/ticketoutputpdf/views.py +++ b/src/pretix/plugins/ticketoutputpdf/views.py @@ -37,7 +37,7 @@ from django.utils.functional import cached_property from django.utils.timezone import now from django.utils.translation import gettext, gettext_lazy as _ from django.views import View -from django.views.generic import CreateView, DeleteView, DetailView, ListView +from django.views.generic import CreateView, DetailView, ListView from reportlab.lib import pagesizes from reportlab.pdfgen import canvas @@ -51,6 +51,7 @@ from pretix.plugins.ticketoutputpdf.forms import TicketLayoutForm from pretix.plugins.ticketoutputpdf.ticketoutput import PdfTicketOutput from ...base.views.tasks import AsyncAction +from ...helpers.compat import CompatDeleteView from .models import TicketLayout from .tasks import tickets_create_pdf @@ -182,7 +183,7 @@ class LayoutSetDefault(EventPermissionRequiredMixin, DetailView): }) -class LayoutDelete(EventPermissionRequiredMixin, DeleteView): +class LayoutDelete(EventPermissionRequiredMixin, CompatDeleteView): model = TicketLayout template_name = 'pretixplugins/ticketoutputpdf/delete.html' permission = 'can_change_event_settings' diff --git a/src/pretix/presale/views/customer.py b/src/pretix/presale/views/customer.py index 878e0de74e..2875b7319a 100644 --- a/src/pretix/presale/views/customer.py +++ b/src/pretix/presale/views/customer.py @@ -44,7 +44,7 @@ from django.utils.translation import gettext_lazy as _ from django.views.decorators.cache import never_cache from django.views.decorators.csrf import csrf_protect from django.views.decorators.debug import sensitive_post_parameters -from django.views.generic import DeleteView, FormView, ListView, View +from django.views.generic import FormView, ListView, View from pretix.base.customersso.oidc import ( oidc_authorize_url, oidc_validate_authorization, @@ -52,6 +52,7 @@ from pretix.base.customersso.oidc import ( from pretix.base.models import Customer, InvoiceAddress, Order, OrderPosition from pretix.base.services.mail import mail from pretix.base.settings import PERSON_NAME_SCHEMES +from pretix.helpers.compat import CompatDeleteView from pretix.helpers.http import redirect_to_url from pretix.multidomain.models import KnownDomain from pretix.multidomain.urlreverse import build_absolute_uri, eventreverse @@ -423,7 +424,7 @@ class MembershipUsageView(CustomerRequiredMixin, ListView): return ctx -class AddressDeleteView(CustomerRequiredMixin, DeleteView): +class AddressDeleteView(CustomerRequiredMixin, CompatDeleteView): template_name = 'pretixpresale/organizers/customer_address_delete.html' context_object_name = 'address' @@ -434,7 +435,7 @@ class AddressDeleteView(CustomerRequiredMixin, DeleteView): return eventreverse(self.request.organizer, 'presale:organizer.customer.profile', kwargs={}) -class ProfileDeleteView(CustomerRequiredMixin, DeleteView): +class ProfileDeleteView(CustomerRequiredMixin, CompatDeleteView): template_name = 'pretixpresale/organizers/customer_profile_delete.html' context_object_name = 'profile'