mirror of
https://github.com/pretix/pretix.git
synced 2026-05-05 15:14:04 +00:00
Fix #349 -- Allow to clone an event
This commit is contained in:
@@ -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):
|
||||
"""
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
{% extends "pretixcontrol/events/create_base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block form %}
|
||||
<p>
|
||||
{% 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 %}
|
||||
</p>
|
||||
<div class="alert alert-info">
|
||||
<strong>
|
||||
{% blocktrans trimmed %}
|
||||
Please make sure to review all settings extensively. You will probably still need to change some
|
||||
settings manually, e.g. date and time settings and texts that contain the event name.
|
||||
{% endblocktrans %}
|
||||
</strong>
|
||||
</div>
|
||||
{% bootstrap_field form.copy_from_event layout="horizontal" %}
|
||||
{% endblock %}
|
||||
@@ -9,7 +9,7 @@ from formtools.wizard.views import SessionWizardView
|
||||
|
||||
from pretix.base.models import Event, EventPermission
|
||||
from pretix.control.forms.event import (
|
||||
EventWizardBasicsForm, EventWizardFoundationForm,
|
||||
EventWizardBasicsForm, EventWizardCopyForm, EventWizardFoundationForm,
|
||||
)
|
||||
|
||||
|
||||
@@ -27,17 +27,25 @@ class EventList(ListView):
|
||||
)
|
||||
|
||||
|
||||
def condition_copy(wizard):
|
||||
return EventPermission.objects.filter(
|
||||
user=wizard.request.user, can_change_settings=True, can_change_items=True
|
||||
).exists()
|
||||
|
||||
|
||||
class EventWizard(SessionWizardView):
|
||||
form_list = [
|
||||
('foundation', EventWizardFoundationForm),
|
||||
('basics', EventWizardBasicsForm),
|
||||
('copy', EventWizardCopyForm),
|
||||
]
|
||||
templates = {
|
||||
'foundation': 'pretixcontrol/events/create_foundation.html',
|
||||
'basics': 'pretixcontrol/events/create_basics.html'
|
||||
'basics': 'pretixcontrol/events/create_basics.html',
|
||||
'copy': 'pretixcontrol/events/create_copy.html',
|
||||
}
|
||||
condition_dict = {
|
||||
|
||||
'copy': condition_copy
|
||||
}
|
||||
|
||||
def get_form_kwargs(self, step=None):
|
||||
@@ -55,6 +63,7 @@ class EventWizard(SessionWizardView):
|
||||
def done(self, form_list, form_dict, **kwargs):
|
||||
foundation_data = self.get_cleaned_data_for_step('foundation')
|
||||
basics_data = self.get_cleaned_data_for_step('basics')
|
||||
copy_data = self.get_cleaned_data_for_step('copy')
|
||||
|
||||
with transaction.atomic():
|
||||
event = form_dict['basics'].instance
|
||||
@@ -63,10 +72,6 @@ class EventWizard(SessionWizardView):
|
||||
form_dict['basics'].save()
|
||||
EventPermission.objects.create(event=event, user=self.request.user)
|
||||
|
||||
event.settings.set('timezone', basics_data['timezone'])
|
||||
event.settings.set('locale', basics_data['locale'])
|
||||
event.settings.set('locales', foundation_data['locales'])
|
||||
|
||||
logdata = {}
|
||||
for f in form_list:
|
||||
logdata.update({
|
||||
@@ -74,7 +79,16 @@ class EventWizard(SessionWizardView):
|
||||
})
|
||||
event.log_action('pretix.event.settings', user=self.request.user, data=logdata)
|
||||
|
||||
messages.success(self.request, _('The new event has been created.'))
|
||||
if copy_data and copy_data['copy_from_event']:
|
||||
from_event = copy_data['copy_from_event']
|
||||
event.copy_data_from(from_event)
|
||||
|
||||
event.settings.set('timezone', basics_data['timezone'])
|
||||
event.settings.set('locale', basics_data['locale'])
|
||||
event.settings.set('locales', foundation_data['locales'])
|
||||
|
||||
messages.success(self.request, _('The new event has been created. You can now adjust the event settings in '
|
||||
'detail.'))
|
||||
return redirect(reverse('control:event.settings', kwargs={
|
||||
'organizer': event.organizer.slug,
|
||||
'event': event.slug,
|
||||
|
||||
Reference in New Issue
Block a user