diff --git a/src/pretix/base/models/event.py b/src/pretix/base/models/event.py index 6904a8563e..6cf56ce223 100644 --- a/src/pretix/base/models/event.py +++ b/src/pretix/base/models/event.py @@ -4,10 +4,12 @@ from datetime import date, datetime, time import pytz from django.conf import settings from django.core.exceptions import ValidationError +from django.core.files.storage import default_storage from django.core.mail import get_connection from django.core.validators import RegexValidator from django.db import models from django.template.defaultfilters import date as _date +from django.utils.crypto import get_random_string from django.utils.functional import cached_property from django.utils.timezone import make_aware, now from django.utils.translation import ugettext_lazy as _ @@ -224,6 +226,73 @@ class Event(LoggedModel): time(hour=23, minute=59, second=59) ), tz) + def copy_data_from(self, other): + from . import ItemCategory, Item, Question, Quota + self.plugins = other.plugins + self.save() + + category_map = {} + for c in ItemCategory.objects.filter(event=other): + category_map[c.pk] = c + c.pk = None + c.event = self + c.save() + + item_map = {} + variation_map = {} + for i in Item.objects.filter(event=other).prefetch_related('variations'): + vars = list(i.variations.all()) + item_map[i.pk] = i + i.pk = None + i.event = self + if i.picture: + i.picture.save(i.picture.name, i.picture) + if i.category_id: + i.category = category_map[i.category_id] + i.save() + for v in vars: + variation_map[v.pk] = v + v.pk = None + v.item = i + v.save() + + for q in Quota.objects.filter(event=other).prefetch_related('items', 'variations'): + items = list(q.items.all()) + vars = list(q.variations.all()) + q.pk = None + q.event = self + q.save() + for i in items: + q.items.add(item_map[i.pk]) + for v in vars: + q.variations.add(variation_map[v.pk]) + + for q in Question.objects.filter(event=other).prefetch_related('items', 'options'): + items = list(q.items.all()) + opts = list(q.options.all()) + q.pk = None + q.event = self + q.save() + for i in items: + q.items.add(item_map[i.pk]) + for o in opts: + o.pk = None + o.question = q + o.save() + + for s in EventSetting.objects.filter(object=other): + s.object = self + s.pk = None + if s.value.startswith('file://'): + fi = default_storage.open(s.value[7:], 'rb') + nonce = get_random_string(length=8) + fname = '%s/%s/%s.%s.%s' % ( + self.organizer.slug, self.slug, s.key, nonce, s.value.split('.')[-1] + ) + newname = default_storage.save(fname, fi) + s.value = 'file://' + newname + s.save() + class EventPermission(models.Model): """ diff --git a/src/pretix/control/forms/event.py b/src/pretix/control/forms/event.py index e24db36a56..777e9dee08 100644 --- a/src/pretix/control/forms/event.py +++ b/src/pretix/control/forms/event.py @@ -26,22 +26,13 @@ class EventWizardFoundationForm(forms.Form): self.fields['organizer'] = forms.ModelChoiceField( label=_("Organizer"), queryset=Organizer.objects.filter( - id__in=self.user.organizer_perms.filter(can_create_events=True).values_list('id', flat=True) + id__in=self.user.organizer_perms.filter(can_create_events=True).values_list('organizer', flat=True) ), widget=forms.RadioSelect, empty_label=None, required=True ) - def clean_slug(self): - slug = self.cleaned_data['slug'] - if Event.objects.filter(slug=slug, organizer=self.organizer).exists(): - raise forms.ValidationError( - self.error_messages['duplicate_slug'], - code='duplicate_slug' - ) - return slug - class EventWizardBasicsForm(I18nModelForm): error_messages = { @@ -100,6 +91,26 @@ class EventWizardBasicsForm(I18nModelForm): return slug +class EventWizardCopyForm(forms.Form): + + def __init__(self, *args, **kwargs): + kwargs.pop('organizer') + kwargs.pop('locales') + self.user = kwargs.pop('user') + super().__init__(*args, **kwargs) + self.fields['copy_from_event'] = forms.ModelChoiceField( + label=_("Copy configuration from"), + queryset=Event.objects.filter( + id__in=self.user.event_perms.filter( + can_change_items=True, can_change_settings=True + ).values_list('event', flat=True) + ), + widget=forms.RadioSelect, + empty_label=_('Do not copy'), + required=True + ) + + class EventUpdateForm(I18nModelForm): def clean_slug(self): return self.instance.slug diff --git a/src/pretix/control/templates/pretixcontrol/events/create_copy.html b/src/pretix/control/templates/pretixcontrol/events/create_copy.html new file mode 100644 index 0000000000..027924d1ca --- /dev/null +++ b/src/pretix/control/templates/pretixcontrol/events/create_copy.html @@ -0,0 +1,20 @@ +{% extends "pretixcontrol/events/create_base.html" %} +{% load i18n %} +{% load bootstrap3 %} +{% block form %} +
+ {% blocktrans trimmed %} + Do you want to copy over your configuration from a different event? We will copy all + products, categories, quotas, and questions as well as general event settings. + {% endblocktrans %} +
+