mirror of
https://github.com/pretix/pretix.git
synced 2026-05-05 15:14:04 +00:00
Bump Django to 4.1.* (#2989)
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
|
||||
from decimal import Decimal
|
||||
from urllib.parse import urlencode, urlparse
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
from django import forms
|
||||
from django.conf import settings
|
||||
@@ -55,7 +56,7 @@ from django_countries.fields import LazyTypedChoiceField
|
||||
from i18nfield.forms import (
|
||||
I18nForm, I18nFormField, I18nFormSetMixin, I18nTextarea, I18nTextInput,
|
||||
)
|
||||
from pytz import common_timezones, timezone
|
||||
from pytz import common_timezones
|
||||
|
||||
from pretix.base.channels import get_all_sales_channels
|
||||
from pretix.base.email import get_available_placeholders
|
||||
@@ -221,7 +222,7 @@ class EventWizardBasicsForm(I18nModelForm):
|
||||
})
|
||||
|
||||
# change timezone
|
||||
zone = timezone(data.get('timezone'))
|
||||
zone = ZoneInfo(data.get('timezone'))
|
||||
data['date_from'] = self.reset_timezone(zone, data.get('date_from'))
|
||||
data['date_to'] = self.reset_timezone(zone, data.get('date_to'))
|
||||
data['presale_start'] = self.reset_timezone(zone, data.get('presale_start'))
|
||||
@@ -230,7 +231,7 @@ class EventWizardBasicsForm(I18nModelForm):
|
||||
|
||||
@staticmethod
|
||||
def reset_timezone(tz, dt):
|
||||
return tz.localize(dt.replace(tzinfo=None)) if dt is not None else None
|
||||
return dt.replace(tzinfo=tz) if dt is not None else None
|
||||
|
||||
def clean_slug(self):
|
||||
slug = self.cleaned_data['slug']
|
||||
|
||||
@@ -747,7 +747,7 @@ class ItemVariationsFormSet(I18nFormSet):
|
||||
|
||||
def _should_delete_form(self, form):
|
||||
should_delete = super()._should_delete_form(form)
|
||||
if should_delete and (form.instance.orderposition_set.exists() or form.instance.cartposition_set.exists()):
|
||||
if should_delete and form.instance.pk and (form.instance.orderposition_set.exists() or form.instance.cartposition_set.exists()):
|
||||
form._delete_fail = True
|
||||
return False
|
||||
return form.cleaned_data.get(DELETION_FIELD_NAME, False)
|
||||
|
||||
@@ -602,7 +602,7 @@ class WebHookForm(forms.ModelForm):
|
||||
mark_safe('{} – <code>{}</code>'.format(a.verbose_name, a.action_type))
|
||||
) for a in get_all_webhook_events().values()
|
||||
]
|
||||
if self.instance:
|
||||
if self.instance and self.instance.pk:
|
||||
self.fields['events'].initial = list(self.instance.listeners.values_list('action_type', flat=True))
|
||||
|
||||
class Meta:
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
from bootstrap3.renderers import FieldRenderer, InlineFieldRenderer
|
||||
from bootstrap3.text import text_value
|
||||
from django.forms import CheckboxInput
|
||||
from django.forms.utils import flatatt
|
||||
@@ -28,6 +27,8 @@ from django.utils.safestring import mark_safe
|
||||
from django.utils.translation import pgettext
|
||||
from i18nfield.forms import I18nFormField
|
||||
|
||||
from pretix.base.forms.renderers import FieldRenderer, InlineFieldRenderer
|
||||
|
||||
|
||||
def render_label(content, label_for=None, label_class=None, label_title='', optional=False):
|
||||
"""
|
||||
|
||||
@@ -39,7 +39,6 @@ from decimal import Decimal
|
||||
|
||||
import bleach
|
||||
import dateutil.parser
|
||||
import pytz
|
||||
from django.dispatch import receiver
|
||||
from django.urls import reverse
|
||||
from django.utils.formats import date_format
|
||||
@@ -209,7 +208,7 @@ def _display_checkin(event, logentry):
|
||||
if 'datetime' in data:
|
||||
dt = dateutil.parser.parse(data.get('datetime'))
|
||||
show_dt = abs((logentry.datetime - dt).total_seconds()) > 5 or 'forced' in data
|
||||
tz = pytz.timezone(event.settings.timezone)
|
||||
tz = event.timezone
|
||||
dt_formatted = date_format(dt.astimezone(tz), "SHORT_DATETIME_FORMAT")
|
||||
|
||||
if 'list' in data:
|
||||
@@ -627,7 +626,7 @@ def pretixcontrol_logentry_display(sender: Event, logentry: LogEntry, **kwargs):
|
||||
if logentry.action_type == 'pretix.control.views.checkin':
|
||||
# deprecated
|
||||
dt = dateutil.parser.parse(data.get('datetime'))
|
||||
tz = pytz.timezone(sender.settings.timezone)
|
||||
tz = sender.timezone
|
||||
dt_formatted = date_format(dt.astimezone(tz), "SHORT_DATETIME_FORMAT")
|
||||
if 'list' in data:
|
||||
try:
|
||||
|
||||
@@ -33,8 +33,7 @@
|
||||
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations under the License.
|
||||
|
||||
from django.conf.urls import re_path
|
||||
from django.urls import include
|
||||
from django.urls import include, re_path
|
||||
from django.views.generic.base import RedirectView
|
||||
|
||||
from pretix.control.views import (
|
||||
|
||||
@@ -19,18 +19,7 @@
|
||||
# You should have received a copy of the GNU Affero General Public License along with this program. If not, see
|
||||
# <https://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
# This file is based on an earlier version of pretix which was released under the Apache License 2.0. The full text of
|
||||
# the Apache License 2.0 can be obtained at <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||
#
|
||||
# This file may have since been changed and any changes are released under the terms of AGPLv3 as described above. A
|
||||
# full history of changes and contributors is available at <https://github.com/pretix/pretix>.
|
||||
#
|
||||
# This file contains Apache-licensed contributions copyrighted by: Jakob Schnell, jasonwaiting@live.hk, pajowu
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software distributed under the Apache License 2.0 is
|
||||
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations under the License.
|
||||
from datetime import timezone
|
||||
|
||||
import dateutil.parser
|
||||
from django.contrib import messages
|
||||
@@ -44,7 +33,6 @@ 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 ListView
|
||||
from pytz import UTC
|
||||
|
||||
from pretix.base.channels import get_all_sales_channels
|
||||
from pretix.base.models import Checkin, Order, OrderPosition
|
||||
@@ -60,6 +48,18 @@ from pretix.control.views import CreateView, PaginationMixin, UpdateView
|
||||
from pretix.helpers.compat import CompatDeleteView
|
||||
from pretix.helpers.models import modelcopy
|
||||
|
||||
# This file is based on an earlier version of pretix which was released under the Apache License 2.0. The full text of
|
||||
# the Apache License 2.0 can be obtained at <http://www.apache.org/licenses/LICENSE-2.0>.
|
||||
#
|
||||
# This file may have since been changed and any changes are released under the terms of AGPLv3 as described above. A
|
||||
# full history of changes and contributors is available at <https://github.com/pretix/pretix>.
|
||||
#
|
||||
# This file contains Apache-licensed contributions copyrighted by: Jakob Schnell, jasonwaiting@live.hk, pajowu
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software distributed under the Apache License 2.0 is
|
||||
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations under the License.
|
||||
|
||||
|
||||
class CheckInListQueryMixin:
|
||||
|
||||
@@ -163,20 +163,20 @@ class CheckInListShow(EventPermissionRequiredMixin, PaginationMixin, CheckInList
|
||||
if e.last_entry:
|
||||
if isinstance(e.last_entry, str):
|
||||
# Apparently only happens on SQLite
|
||||
e.last_entry_aware = make_aware(dateutil.parser.parse(e.last_entry), UTC)
|
||||
e.last_entry_aware = make_aware(dateutil.parser.parse(e.last_entry), timezone.utc)
|
||||
elif not is_aware(e.last_entry):
|
||||
# Apparently only happens on MySQL
|
||||
e.last_entry_aware = make_aware(e.last_entry, UTC)
|
||||
e.last_entry_aware = make_aware(e.last_entry, timezone.utc)
|
||||
else:
|
||||
# This would be correct, so guess on which database it works… Yes, it's PostgreSQL.
|
||||
e.last_entry_aware = e.last_entry
|
||||
if e.last_exit:
|
||||
if isinstance(e.last_exit, str):
|
||||
# Apparently only happens on SQLite
|
||||
e.last_exit_aware = make_aware(dateutil.parser.parse(e.last_exit), UTC)
|
||||
e.last_exit_aware = make_aware(dateutil.parser.parse(e.last_exit), timezone.utc)
|
||||
elif not is_aware(e.last_exit):
|
||||
# Apparently only happens on MySQL
|
||||
e.last_exit_aware = make_aware(e.last_exit, UTC)
|
||||
e.last_exit_aware = make_aware(e.last_exit, timezone.utc)
|
||||
else:
|
||||
# This would be correct, so guess on which database it works… Yes, it's PostgreSQL.
|
||||
e.last_exit_aware = e.last_exit
|
||||
|
||||
@@ -34,8 +34,8 @@
|
||||
|
||||
from datetime import timedelta
|
||||
from decimal import Decimal
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import pytz
|
||||
from django.conf import settings
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.db.models import (
|
||||
@@ -510,7 +510,7 @@ def widgets_for_event_qs(request, qs, user, nmax, lazy=False):
|
||||
for event in events:
|
||||
if not lazy:
|
||||
tzname = event.cache.get_or_set('timezone', lambda: event.settings.timezone)
|
||||
tz = pytz.timezone(tzname)
|
||||
tz = ZoneInfo(tzname)
|
||||
if event.has_subevents:
|
||||
if event.min_from is None:
|
||||
dr = pgettext("subevent", "No dates")
|
||||
|
||||
@@ -41,6 +41,7 @@ from decimal import Decimal
|
||||
from io import BytesIO
|
||||
from itertools import groupby
|
||||
from urllib.parse import urlsplit
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import bleach
|
||||
import qrcode
|
||||
@@ -67,7 +68,6 @@ from django.views.generic.base import TemplateView, View
|
||||
from django.views.generic.detail import SingleObjectMixin
|
||||
from i18nfield.strings import LazyI18nString
|
||||
from i18nfield.utils import I18nJSONEncoder
|
||||
from pytz import timezone
|
||||
|
||||
from pretix.base.channels import get_all_sales_channels
|
||||
from pretix.base.email import get_available_placeholders
|
||||
@@ -253,7 +253,7 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
|
||||
self.item_meta_property_formset.is_valid() and self.confirm_texts_formset.is_valid() and \
|
||||
self.footer_links_formset.is_valid():
|
||||
# reset timezone
|
||||
zone = timezone(self.sform.cleaned_data['timezone'])
|
||||
zone = ZoneInfo(self.sform.cleaned_data['timezone'])
|
||||
event = form.instance
|
||||
event.date_from = self.reset_timezone(zone, event.date_from)
|
||||
event.date_to = self.reset_timezone(zone, event.date_to)
|
||||
@@ -266,7 +266,7 @@ class EventUpdate(DecoupleMixin, EventSettingsViewMixin, EventPermissionRequired
|
||||
|
||||
@staticmethod
|
||||
def reset_timezone(tz, dt):
|
||||
return tz.localize(dt.replace(tzinfo=None)) if dt is not None else None
|
||||
return dt.replace(tzinfo=tz) if dt is not None else None
|
||||
|
||||
@cached_property
|
||||
def item_meta_property_formset(self):
|
||||
|
||||
@@ -60,8 +60,7 @@ from django.utils.timezone import get_current_timezone, now
|
||||
from django.utils.translation import gettext, gettext_lazy as _
|
||||
from django.views import View
|
||||
from django.views.generic import (
|
||||
CreateView, DeleteView, DetailView, FormView, ListView, TemplateView,
|
||||
UpdateView,
|
||||
CreateView, DetailView, FormView, ListView, TemplateView, UpdateView,
|
||||
)
|
||||
|
||||
from pretix.api.models import ApiCall, WebHook
|
||||
@@ -1775,7 +1774,7 @@ class ExportView(OrganizerPermissionRequiredMixin, ExportMixin, ListView):
|
||||
instance = self.scheduled or ScheduledOrganizerExport(
|
||||
organizer=self.request.organizer,
|
||||
owner=self.request.user,
|
||||
timezone=get_current_timezone().zone,
|
||||
timezone=str(get_current_timezone()),
|
||||
)
|
||||
if not self.scheduled:
|
||||
initial = {
|
||||
@@ -1811,7 +1810,7 @@ class ExportView(OrganizerPermissionRequiredMixin, ExportMixin, ListView):
|
||||
return ctx
|
||||
|
||||
|
||||
class DeleteScheduledExportView(OrganizerPermissionRequiredMixin, ExportMixin, DeleteView):
|
||||
class DeleteScheduledExportView(OrganizerPermissionRequiredMixin, ExportMixin, CompatDeleteView):
|
||||
template_name = 'pretixcontrol/organizers/export_delete.html'
|
||||
context_object_name = 'export'
|
||||
|
||||
|
||||
@@ -260,7 +260,7 @@ class SubEventEditorMixin(MetaDataEditorMixin):
|
||||
form=SimpleCheckinListForm, formset=CheckinListFormSet,
|
||||
can_order=False, can_delete=True, extra=extra,
|
||||
)
|
||||
if self.object:
|
||||
if self.object and self.object.pk:
|
||||
kwargs['queryset'] = self.object.checkinlist_set.prefetch_related('limit_products')
|
||||
|
||||
return formsetclass(self.request.POST if self.request.method == "POST" else None,
|
||||
@@ -297,7 +297,7 @@ class SubEventEditorMixin(MetaDataEditorMixin):
|
||||
form=QuotaForm, formset=QuotaFormSet, min_num=1, validate_min=True,
|
||||
can_order=False, can_delete=True, extra=extra,
|
||||
)
|
||||
if self.object:
|
||||
if self.object and self.object.pk:
|
||||
kwargs['queryset'] = self.object.quotas.prefetch_related('items', 'variations')
|
||||
|
||||
return formsetclass(
|
||||
@@ -400,10 +400,10 @@ class SubEventEditorMixin(MetaDataEditorMixin):
|
||||
def itemvar_forms(self):
|
||||
se_item_instances = {
|
||||
sei.item_id: sei for sei in SubEventItem.objects.filter(subevent=self.object)
|
||||
}
|
||||
} if self.object and self.object.pk else {}
|
||||
se_var_instances = {
|
||||
sei.variation_id: sei for sei in SubEventItemVariation.objects.filter(subevent=self.object)
|
||||
}
|
||||
} if self.object and self.object.pk else {}
|
||||
|
||||
if self.copy_from:
|
||||
se_item_instances = {
|
||||
@@ -821,18 +821,18 @@ class SubEventBulkCreate(SubEventEditorMixin, EventPermissionRequiredMixin, Asyn
|
||||
for t in self.get_times():
|
||||
se = copy.copy(form.instance)
|
||||
|
||||
se.date_from = make_aware(datetime.combine(rdate, t['time_from']), tz, is_dst=False)
|
||||
se.date_from = make_aware(datetime.combine(rdate, t['time_from'].replace(fold=1)), tz)
|
||||
|
||||
if t.get('time_to'):
|
||||
se.date_to = (
|
||||
make_aware(datetime.combine(rdate, t['time_to']), tz, is_dst=False)
|
||||
make_aware(datetime.combine(rdate, t['time_to'].replace(fold=1)), tz)
|
||||
if t.get('time_to') > t.get('time_from')
|
||||
else make_aware(datetime.combine(rdate + timedelta(days=1), t['time_to']), tz, is_dst=False)
|
||||
else make_aware(datetime.combine(rdate + timedelta(days=1), t['time_to'].replace(fold=1)), tz)
|
||||
)
|
||||
else:
|
||||
se.date_to = None
|
||||
se.date_admission = (
|
||||
make_aware(datetime.combine(rdate, t['time_admission'].replace(fold=1)), tz, is_dst=False)
|
||||
make_aware(datetime.combine(rdate, t['time_admission'].replace(fold=1)), tz)
|
||||
if t.get('time_admission')
|
||||
else None
|
||||
)
|
||||
@@ -1148,6 +1148,7 @@ class SubEventBulkEdit(SubEventQueryMixin, EventPermissionRequiredMixin, FormVie
|
||||
subevents = list(self.get_queryset().prefetch_related('checkinlist_set'))
|
||||
to_save_products = []
|
||||
to_save_gates = []
|
||||
to_delete_list_ids = []
|
||||
|
||||
for f in self.list_formset.forms:
|
||||
if self.list_formset._should_delete_form(f) and f in self.list_formset.extra_forms:
|
||||
@@ -1159,7 +1160,7 @@ class SubEventBulkEdit(SubEventQueryMixin, EventPermissionRequiredMixin, FormVie
|
||||
log_entries += [
|
||||
q.log_action(action='pretix.event.checkinlist.deleted', user=self.request.user, save=False),
|
||||
]
|
||||
q.delete()
|
||||
to_delete_list_ids.append(q.pk)
|
||||
elif f in self.list_formset.extra_forms:
|
||||
change_data = {k: f.cleaned_data.get(k) for k in f.changed_data}
|
||||
for se in subevents:
|
||||
@@ -1198,6 +1199,8 @@ class SubEventBulkEdit(SubEventQueryMixin, EventPermissionRequiredMixin, FormVie
|
||||
CheckinList.limit_products.through.objects.bulk_create(to_save_products)
|
||||
if to_save_gates:
|
||||
CheckinList.gates.through.objects.bulk_create(to_save_gates)
|
||||
if to_delete_list_ids:
|
||||
CheckinList.objects.filter(id__in=to_delete_list_ids).delete()
|
||||
|
||||
def save_quota_formset(self, log_entries):
|
||||
if not self.quota_formset.has_changed():
|
||||
@@ -1224,6 +1227,7 @@ class SubEventBulkEdit(SubEventQueryMixin, EventPermissionRequiredMixin, FormVie
|
||||
|
||||
if to_delete_quota_ids:
|
||||
Quota.objects.filter(id__in=to_delete_quota_ids).delete()
|
||||
to_delete_quota_ids = []
|
||||
|
||||
for f in self.quota_formset.forms:
|
||||
if self.quota_formset._should_delete_form(f) and f in self.quota_formset.extra_forms:
|
||||
@@ -1245,7 +1249,7 @@ class SubEventBulkEdit(SubEventQueryMixin, EventPermissionRequiredMixin, FormVie
|
||||
'id': q.pk
|
||||
}, save=False)
|
||||
]
|
||||
q.delete()
|
||||
to_delete_quota_ids.append(q.pk)
|
||||
elif f in self.quota_formset.extra_forms:
|
||||
change_data = {k: f.cleaned_data.get(k) for k in f.changed_data}
|
||||
for se in subevents:
|
||||
@@ -1288,6 +1292,8 @@ class SubEventBulkEdit(SubEventQueryMixin, EventPermissionRequiredMixin, FormVie
|
||||
Quota.items.through.objects.bulk_create(to_save_items)
|
||||
if to_save_variations:
|
||||
Quota.variations.through.objects.bulk_create(to_save_variations)
|
||||
if to_delete_quota_ids:
|
||||
Quota.objects.filter(id__in=to_delete_quota_ids).delete()
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
ctx = super().get_context_data(**kwargs)
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
# License for the specific language governing permissions and limitations under the License.
|
||||
|
||||
from datetime import datetime, time
|
||||
from zoneinfo import ZoneInfo
|
||||
|
||||
import pytz
|
||||
from dateutil.parser import parse
|
||||
from django.core.exceptions import PermissionDenied
|
||||
from django.db.models import F, Max, Min, Q
|
||||
@@ -88,7 +88,7 @@ def serialize_event(e):
|
||||
if e.min_from is None:
|
||||
dr = pgettext('subevent', 'No dates')
|
||||
else:
|
||||
tz = pytz.timezone(e.settings.timezone)
|
||||
tz = ZoneInfo(e.settings.timezone)
|
||||
dr = _('Series:') + ' ' + daterange(
|
||||
e.min_from.astimezone(tz),
|
||||
(e.max_fromto or e.max_to or e.max_from).astimezone(tz)
|
||||
|
||||
Reference in New Issue
Block a user