mirror of
https://github.com/pretix/pretix.git
synced 2026-05-07 15:34:02 +00:00
Basic event settings
This commit is contained in:
@@ -3,6 +3,7 @@ from django.conf import settings
|
|||||||
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
|
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.template.defaultfilters import date as _date
|
from django.template.defaultfilters import date as _date
|
||||||
|
from django.core.validators import RegexValidator
|
||||||
|
|
||||||
|
|
||||||
class UserManager(BaseUserManager):
|
class UserManager(BaseUserManager):
|
||||||
@@ -215,8 +216,19 @@ class Event(models.Model):
|
|||||||
on_delete=models.PROTECT)
|
on_delete=models.PROTECT)
|
||||||
name = models.CharField(max_length=200,
|
name = models.CharField(max_length=200,
|
||||||
verbose_name=_("Name"))
|
verbose_name=_("Name"))
|
||||||
slug = models.CharField(max_length=50, db_index=True,
|
slug = models.CharField(
|
||||||
verbose_name=_("Slug"))
|
max_length=50, db_index=True,
|
||||||
|
help_text=_(
|
||||||
|
"Should be short, only contain lowercase letters and numbers, and must be unique among your events. "
|
||||||
|
+ "This is being used in addresses and bank transfer references."),
|
||||||
|
validators=[
|
||||||
|
RegexValidator(
|
||||||
|
regex="^[a-zA-Z0-9.-]+$",
|
||||||
|
message=_("The slug may only contain letters, numbers, dots and dashes."),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
verbose_name=_("Slug"),
|
||||||
|
)
|
||||||
permitted = models.ManyToManyField(User, through='EventPermission',
|
permitted = models.ManyToManyField(User, through='EventPermission',
|
||||||
related_name="events",)
|
related_name="events",)
|
||||||
locale = models.CharField(max_length=10,
|
locale = models.CharField(max_length=10,
|
||||||
@@ -232,27 +244,33 @@ class Event(models.Model):
|
|||||||
verbose_name=_("Event end time"))
|
verbose_name=_("Event end time"))
|
||||||
show_date_to = models.BooleanField(
|
show_date_to = models.BooleanField(
|
||||||
default=True,
|
default=True,
|
||||||
verbose_name=_("Show event end date")
|
verbose_name=_("Show event end date"),
|
||||||
|
help_text=("If disabled, only event's start date will be displayed to the public."),
|
||||||
)
|
)
|
||||||
show_times = models.BooleanField(
|
show_times = models.BooleanField(
|
||||||
default=True,
|
default=True,
|
||||||
verbose_name=_("Show dates with time")
|
verbose_name=_("Show dates with time"),
|
||||||
|
help_text=("If disabled, the event's start and end date will be displayed without the time of day."),
|
||||||
)
|
)
|
||||||
presale_end = models.DateTimeField(
|
presale_end = models.DateTimeField(
|
||||||
null=True, blank=True,
|
null=True, blank=True,
|
||||||
verbose_name=_("End of presale")
|
verbose_name=_("End of presale"),
|
||||||
|
help_text=_("No items will be sold after this date."),
|
||||||
)
|
)
|
||||||
presale_start = models.DateTimeField(
|
presale_start = models.DateTimeField(
|
||||||
null=True, blank=True,
|
null=True, blank=True,
|
||||||
verbose_name=_("Start of presale")
|
verbose_name=_("Start of presale"),
|
||||||
|
help_text=_("No items will be sold before this date."),
|
||||||
)
|
)
|
||||||
payment_term_days = models.IntegerField(
|
payment_term_days = models.IntegerField(
|
||||||
default=14,
|
default=14,
|
||||||
verbose_name=_("Payment term in days")
|
verbose_name=_("Payment term in days"),
|
||||||
|
help_text=_("The number of days after placing an order the user has to pay to preserve his reservation."),
|
||||||
)
|
)
|
||||||
payment_term_last = models.DateTimeField(
|
payment_term_last = models.DateTimeField(
|
||||||
null=True, blank=True,
|
null=True, blank=True,
|
||||||
verbose_name=_("Last date of payments")
|
verbose_name=_("Last date of payments"),
|
||||||
|
help_text=_("The last date any payments are accepted. This has precedence over the number of days configured above.")
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_date_from_display(self):
|
def get_date_from_display(self):
|
||||||
|
|||||||
32
src/tixlcontrol/permissions.py
Normal file
32
src/tixlcontrol/permissions.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
from django.http import HttpResponseForbidden
|
||||||
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
|
from tixlbase.models import EventPermission
|
||||||
|
|
||||||
|
|
||||||
|
def event_permission_required(function, permission):
|
||||||
|
def wrapper(request, *args, **kw):
|
||||||
|
if not request.user.is_authenticated():
|
||||||
|
return HttpResponseForbidden()
|
||||||
|
perm = EventPermission.objects.get(
|
||||||
|
event=request.event,
|
||||||
|
user=request.user
|
||||||
|
)
|
||||||
|
allowed = False
|
||||||
|
try:
|
||||||
|
allowed = getattr(perm, permission)
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
if allowed:
|
||||||
|
return function(request, *args, **kw)
|
||||||
|
return HttpResponseForbidden(_('You do not have permission to view this content.'))
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
class EventPermissionRequiredMixin:
|
||||||
|
permission = ''
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def as_view(cls, **initkwargs):
|
||||||
|
view = super(EventPermissionRequiredMixin, cls).as_view(**initkwargs)
|
||||||
|
return event_permission_required(view, cls.permission)
|
||||||
@@ -15,6 +15,6 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
<li {% if url_name == "event.index" %}class="active"{% endif %}><a href="{% url 'control:index' %}">{% trans "Dashboard" %}</a></li>
|
<li {% if url_name == "event.index" %}class="active"{% endif %}><a href="{% url 'control:event.index' organizer=request.event.organizer.slug event=request.event.slug %}">{% trans "Dashboard" %}</a></li>
|
||||||
<li {% if "event.settings" in url_name %}class="active"{% endif %}><a href="">{% trans "Settings" %}</a></li>
|
<li {% if url_name == "event.settings" %}class="active"{% endif %}><a href="{% url 'control:event.settings' organizer=request.event.organizer.slug event=request.event.slug %}">{% trans "Settings" %}</a></li>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
42
src/tixlcontrol/templates/tixlcontrol/event/settings.html
Normal file
42
src/tixlcontrol/templates/tixlcontrol/event/settings.html
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
{% extends "tixlcontrol/event/base.html" %}
|
||||||
|
{% load i18n %}
|
||||||
|
{% load bootstrap3 %}
|
||||||
|
{% block title %}{{ request.event.name }}{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<h1>{% trans "Settings" %}</h1>
|
||||||
|
<form action="" method="post" class="form-horizontal">
|
||||||
|
{% csrf_token %}
|
||||||
|
<fieldset>
|
||||||
|
<legend>{% trans "General information" %}</legend>
|
||||||
|
{% bootstrap_field form.name layout="horizontal" %}
|
||||||
|
{% bootstrap_field form.slug layout="horizontal" %}
|
||||||
|
{% bootstrap_field form.date_from layout="horizontal" %}
|
||||||
|
{% bootstrap_field form.date_to layout="horizontal" %}
|
||||||
|
{% bootstrap_field form.currency layout="horizontal" %}
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>{% trans "Display settings" %}</legend>
|
||||||
|
{% bootstrap_field form.locale layout="horizontal" %}
|
||||||
|
{% bootstrap_field form.timezone layout="horizontal" %}
|
||||||
|
{% bootstrap_field form.show_date_to layout="horizontal" %}
|
||||||
|
{% bootstrap_field form.show_times layout="horizontal" %}
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>{% trans "Presale settings" %}</legend>
|
||||||
|
{% bootstrap_field form.presale_start layout="horizontal" %}
|
||||||
|
{% bootstrap_field form.presale_end layout="horizontal" %}
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>{% trans "Payment settings" %}</legend>
|
||||||
|
{% bootstrap_field form.payment_term_days layout="horizontal" %}
|
||||||
|
{% bootstrap_field form.payment_term_last layout="horizontal" %}
|
||||||
|
</fieldset>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-offset-2 col-sm-10">
|
||||||
|
<button type="submit" class="btn btn-primary">
|
||||||
|
{% trans "Save" %}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
from django.conf.urls import patterns, url
|
from django.conf.urls import patterns, url
|
||||||
from tixlcontrol.views import main
|
from tixlcontrol.views import main, event
|
||||||
|
|
||||||
urlpatterns = patterns('',
|
urlpatterns = patterns('',
|
||||||
url(r'^$', 'tixlcontrol.views.main.index', name='index'),
|
url(r'^$', 'tixlcontrol.views.main.index', name='index'),
|
||||||
url(r'^event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/$', 'tixlcontrol.views.event.index', name='event.index'),
|
url(r'^event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/$', 'tixlcontrol.views.event.index', name='event.index'),
|
||||||
|
url(r'^event/(?P<organizer>[^/]+)/(?P<event>[^/]+)/settings$', event.EventUpdate.as_view(), name='event.settings'),
|
||||||
url(r'^events/$', main.EventList.as_view(), name='events'),
|
url(r'^events/$', main.EventList.as_view(), name='events'),
|
||||||
url(r'^logout$', 'tixlcontrol.views.auth.logout', name='auth.logout'),
|
url(r'^logout$', 'tixlcontrol.views.auth.logout', name='auth.logout'),
|
||||||
url(r'^login$', 'tixlcontrol.views.auth.login', name='auth.login'),
|
url(r'^login$', 'tixlcontrol.views.auth.login', name='auth.login'),
|
||||||
|
|||||||
@@ -1,4 +1,63 @@
|
|||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
from django.views.generic.edit import UpdateView
|
||||||
|
from django import forms
|
||||||
|
from django.utils.translation import ugettext_lazy as _
|
||||||
|
from django.core.urlresolvers import reverse
|
||||||
|
|
||||||
|
from pytz import common_timezones
|
||||||
|
|
||||||
|
from tixlbase.models import Event
|
||||||
|
from tixlcontrol.permissions import EventPermissionRequiredMixin
|
||||||
|
|
||||||
|
|
||||||
|
class EventUpdateForm(forms.ModelForm):
|
||||||
|
|
||||||
|
timezone = forms.ChoiceField(
|
||||||
|
choices=((a, a) for a in common_timezones),
|
||||||
|
label=_("Default timezone"),
|
||||||
|
)
|
||||||
|
|
||||||
|
def clean_slug(self):
|
||||||
|
return self.instance.slug
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.fields['slug'].widget.attrs['readonly'] = True
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Event
|
||||||
|
localized_fields = '__all__'
|
||||||
|
fields = [
|
||||||
|
'name',
|
||||||
|
'slug',
|
||||||
|
'locale',
|
||||||
|
'timezone',
|
||||||
|
'currency',
|
||||||
|
'date_from',
|
||||||
|
'date_to',
|
||||||
|
'show_date_to',
|
||||||
|
'show_times',
|
||||||
|
'presale_start',
|
||||||
|
'presale_end',
|
||||||
|
'payment_term_days',
|
||||||
|
'payment_term_last',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class EventUpdate(EventPermissionRequiredMixin, UpdateView):
|
||||||
|
model = Event
|
||||||
|
form_class = EventUpdateForm
|
||||||
|
template_name = 'tixlcontrol/event/settings.html'
|
||||||
|
permission = 'can_change_settings'
|
||||||
|
|
||||||
|
def get_object(self, queryset=None):
|
||||||
|
return self.request.event
|
||||||
|
|
||||||
|
def get_success_url(self):
|
||||||
|
return reverse('control:event.settings', kwargs={
|
||||||
|
'organizer': self.get_object().organizer.slug,
|
||||||
|
'event': self.get_object().slug,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
def index(request, organizer, event):
|
def index(request, organizer, event):
|
||||||
|
|||||||
Reference in New Issue
Block a user