forked from CGM_Public/pretix_original
Code documentation improvements
This commit is contained in:
@@ -15,8 +15,9 @@ class EventRelatedCache:
|
|||||||
main purpose of this is to be able to flush all cached data related
|
main purpose of this is to be able to flush all cached data related
|
||||||
to this event at once.
|
to this event at once.
|
||||||
|
|
||||||
The object is stateless, all state is in the cache, so you can
|
The EventRelatedCache instance itself is stateless, all state is
|
||||||
instantiate it as many times as you want.
|
stored in the cache backend, so you can instantiate this class as many
|
||||||
|
times as you want.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, event: Event, cache: str='default'):
|
def __init__(self, event: Event, cache: str='default'):
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ from versions.models import Versionable
|
|||||||
|
|
||||||
|
|
||||||
class VersionedBaseModelForm(BaseModelForm):
|
class VersionedBaseModelForm(BaseModelForm):
|
||||||
|
"""
|
||||||
|
This is a helperclass to construct VersionedModelForm
|
||||||
|
"""
|
||||||
def save(self, commit=True):
|
def save(self, commit=True):
|
||||||
if self.instance.pk is not None and isinstance(self.instance, Versionable):
|
if self.instance.pk is not None and isinstance(self.instance, Versionable):
|
||||||
if self.has_changed():
|
if self.has_changed():
|
||||||
@@ -12,4 +15,11 @@ class VersionedBaseModelForm(BaseModelForm):
|
|||||||
|
|
||||||
|
|
||||||
class VersionedModelForm(six.with_metaclass(ModelFormMetaclass, VersionedBaseModelForm)):
|
class VersionedModelForm(six.with_metaclass(ModelFormMetaclass, VersionedBaseModelForm)):
|
||||||
|
"""
|
||||||
|
This is a modified version of Django's ModelForm which differs from ModelForm in
|
||||||
|
only one way: It executes the .clone() method of an object before saving it back to
|
||||||
|
the database, if the model is a sub-class of versions.models.Versionable. You can
|
||||||
|
safely use this as a base class for all your model forms, it will work out correctly
|
||||||
|
with both versioned and non-versioned models.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -349,7 +349,8 @@ class EventPermission(Versionable):
|
|||||||
|
|
||||||
class ItemCategory(Versionable):
|
class ItemCategory(Versionable):
|
||||||
"""
|
"""
|
||||||
Items can be sorted into categories
|
Items can be sorted into categories, which only have a name and a
|
||||||
|
configurable order
|
||||||
"""
|
"""
|
||||||
event = VersionedForeignKey(
|
event = VersionedForeignKey(
|
||||||
Event,
|
Event,
|
||||||
@@ -385,9 +386,8 @@ class ItemCategory(Versionable):
|
|||||||
|
|
||||||
class Property(Versionable):
|
class Property(Versionable):
|
||||||
"""
|
"""
|
||||||
A property is a modifier which can be applied to an
|
A property is a modifier which can be applied to an Item. For example
|
||||||
Item. For example 'Size' would be a property associated
|
'Size' would be a property associated with the item 'T-Shirt'.
|
||||||
with the item 'T-Shirt'.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
event = VersionedForeignKey(
|
event = VersionedForeignKey(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
try: # NOQA
|
try: # NOQA
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
except ImportError: # NOQA
|
except ImportError: # NOQA
|
||||||
from flufl.enum import Enum
|
from flufl.enum import Enum # remove this dependency when support for python <=3.3 is dropped
|
||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
|
|
||||||
@@ -10,7 +10,10 @@ class PluginType(Enum):
|
|||||||
RESTRICTION = 1
|
RESTRICTION = 1
|
||||||
|
|
||||||
|
|
||||||
def get_all_plugins() -> "class":
|
def get_all_plugins() -> "List[class]":
|
||||||
|
"""
|
||||||
|
Returns the TixlPluginMeta classes of all plugins found in the installed Django apps.
|
||||||
|
"""
|
||||||
plugins = []
|
plugins = []
|
||||||
for app in apps.get_app_configs():
|
for app in apps.get_app_configs():
|
||||||
if hasattr(app, 'TixlPluginMeta'):
|
if hasattr(app, 'TixlPluginMeta'):
|
||||||
|
|||||||
@@ -4,6 +4,11 @@ from django.dispatch.dispatcher import NO_RECEIVERS
|
|||||||
|
|
||||||
|
|
||||||
class EventPluginSignal(django.dispatch.Signal):
|
class EventPluginSignal(django.dispatch.Signal):
|
||||||
|
"""
|
||||||
|
This is an extension to Django's built-in signals which differs in a way that it sends
|
||||||
|
out it's events only to receivers which belong to plugins that are enabled for the given
|
||||||
|
Event.
|
||||||
|
"""
|
||||||
|
|
||||||
def send(self, sender, **named):
|
def send(self, sender, **named):
|
||||||
"""
|
"""
|
||||||
@@ -34,6 +39,11 @@ class EventPluginSignal(django.dispatch.Signal):
|
|||||||
responses.append((receiver, response))
|
responses.append((receiver, response))
|
||||||
return responses
|
return responses
|
||||||
|
|
||||||
|
"""
|
||||||
|
This signal is sent out every time some component of tixl wants to know whether a specific
|
||||||
|
item or variation is available for sell. The item will only be sold, if all (active) receivers
|
||||||
|
return a positive result (see plugin API documentation for details).
|
||||||
|
"""
|
||||||
determine_availability = EventPluginSignal(
|
determine_availability = EventPluginSignal(
|
||||||
providing_args=["item", "variations", "context", "cache"]
|
providing_args=["item", "variations", "context", "cache"]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
from django.contrib import admin
|
|
||||||
|
|
||||||
# Register your models here.
|
|
||||||
@@ -3,6 +3,9 @@ from django.core.urlresolvers import resolve
|
|||||||
|
|
||||||
|
|
||||||
def contextprocessor(request):
|
def contextprocessor(request):
|
||||||
|
"""
|
||||||
|
Adds data to all template contexts
|
||||||
|
"""
|
||||||
ctx = {
|
ctx = {
|
||||||
'url_name': resolve(request.path_info).url_name,
|
'url_name': resolve(request.path_info).url_name,
|
||||||
'settings': settings,
|
'settings': settings,
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ from tixlbase.models import Event
|
|||||||
class PermissionMiddleware:
|
class PermissionMiddleware:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
This middleware enforces all requests to the control app
|
This middleware enforces all requests to the control app to require login.
|
||||||
to require login.
|
|
||||||
Additionally, it enforces all requests to "control:event." URLs
|
Additionally, it enforces all requests to "control:event." URLs
|
||||||
to be for an event the user has basic access to.
|
to be for an event the user has basic access to.
|
||||||
"""
|
"""
|
||||||
@@ -56,4 +55,5 @@ class PermissionMiddleware:
|
|||||||
organizer__slug=url.kwargs['organizer'],
|
organizer__slug=url.kwargs['organizer'],
|
||||||
)
|
)
|
||||||
except Event.DoesNotExist:
|
except Event.DoesNotExist:
|
||||||
return HttpResponseNotFound(_("The selected event was not found or you have no permission to administrate it."))
|
return HttpResponseNotFound(_("The selected event was not found or you "
|
||||||
|
"have no permission to administrate it."))
|
||||||
|
|||||||
@@ -5,6 +5,10 @@ from tixlbase.models import EventPermission
|
|||||||
|
|
||||||
|
|
||||||
def event_permission_required(permission):
|
def event_permission_required(permission):
|
||||||
|
"""
|
||||||
|
This view decorator rejects all requests with a 403 response which are not from
|
||||||
|
users having the given permission for the event the request is associated with.
|
||||||
|
"""
|
||||||
def decorator(function):
|
def decorator(function):
|
||||||
def wrapper(request, *args, **kw):
|
def wrapper(request, *args, **kw):
|
||||||
if not request.user.is_authenticated():
|
if not request.user.is_authenticated():
|
||||||
@@ -26,6 +30,10 @@ def event_permission_required(permission):
|
|||||||
|
|
||||||
|
|
||||||
class EventPermissionRequiredMixin:
|
class EventPermissionRequiredMixin:
|
||||||
|
"""
|
||||||
|
This mixin is equivalent to the event_permission_required view decorator but
|
||||||
|
is in a form suitable for class-based views.
|
||||||
|
"""
|
||||||
permission = ''
|
permission = ''
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
from tixlbase.signals import EventPluginSignal
|
from tixlbase.signals import EventPluginSignal
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
This signal is sent out to build configuration forms for all restriction formsets
|
||||||
|
(see plugin API documentation for details).
|
||||||
|
"""
|
||||||
restriction_formset = EventPluginSignal(
|
restriction_formset = EventPluginSignal(
|
||||||
providing_args=["item"]
|
providing_args=["item"]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -22,21 +22,30 @@ urlpatterns += patterns(
|
|||||||
url(r'^settings/plugins$', event.EventPlugins.as_view(), name='event.settings.plugins'),
|
url(r'^settings/plugins$', event.EventPlugins.as_view(), name='event.settings.plugins'),
|
||||||
url(r'^items/$', item.ItemList.as_view(), name='event.items'),
|
url(r'^items/$', item.ItemList.as_view(), name='event.items'),
|
||||||
url(r'^items/(?P<item>[0-9a-f-]+)/$', item.ItemUpdateGeneral.as_view(), name='event.item'),
|
url(r'^items/(?P<item>[0-9a-f-]+)/$', item.ItemUpdateGeneral.as_view(), name='event.item'),
|
||||||
url(r'^items/(?P<item>[0-9a-f-]+)/variations$', item.ItemVariations.as_view(), name='event.item.variations'),
|
url(r'^items/(?P<item>[0-9a-f-]+)/variations$', item.ItemVariations.as_view(),
|
||||||
url(r'^items/(?P<item>[0-9a-f-]+)/restrictions$', item.ItemRestrictions.as_view(), name='event.item.restrictions'),
|
name='event.item.variations'),
|
||||||
|
url(r'^items/(?P<item>[0-9a-f-]+)/restrictions$', item.ItemRestrictions.as_view(),
|
||||||
|
name='event.item.restrictions'),
|
||||||
url(r'^categories/$', item.CategoryList.as_view(), name='event.items.categories'),
|
url(r'^categories/$', item.CategoryList.as_view(), name='event.items.categories'),
|
||||||
url(r'^categories/(?P<category>[0-9a-f-]+)/delete$', item.CategoryDelete.as_view(), name='event.items.categories.delete'),
|
url(r'^categories/(?P<category>[0-9a-f-]+)/delete$', item.CategoryDelete.as_view(),
|
||||||
|
name='event.items.categories.delete'),
|
||||||
url(r'^categories/(?P<category>[0-9a-f-]+)/up$', item.category_move_up, name='event.items.categories.up'),
|
url(r'^categories/(?P<category>[0-9a-f-]+)/up$', item.category_move_up, name='event.items.categories.up'),
|
||||||
url(r'^categories/(?P<category>[0-9a-f-]+)/down$', item.category_move_down, name='event.items.categories.down'),
|
url(r'^categories/(?P<category>[0-9a-f-]+)/down$', item.category_move_down,
|
||||||
url(r'^categories/(?P<category>[0-9a-f-]+)/$', item.CategoryUpdate.as_view(), name='event.items.categories.edit'),
|
name='event.items.categories.down'),
|
||||||
|
url(r'^categories/(?P<category>[0-9a-f-]+)/$', item.CategoryUpdate.as_view(),
|
||||||
|
name='event.items.categories.edit'),
|
||||||
url(r'^categories/add$', item.CategoryCreate.as_view(), name='event.items.categories.add'),
|
url(r'^categories/add$', item.CategoryCreate.as_view(), name='event.items.categories.add'),
|
||||||
url(r'^questions/$', item.QuestionList.as_view(), name='event.items.questions'),
|
url(r'^questions/$', item.QuestionList.as_view(), name='event.items.questions'),
|
||||||
url(r'^questions/(?P<question>[0-9a-f-]+)/delete$', item.QuestionDelete.as_view(), name='event.items.questions.delete'),
|
url(r'^questions/(?P<question>[0-9a-f-]+)/delete$', item.QuestionDelete.as_view(),
|
||||||
url(r'^questions/(?P<question>[0-9a-f-]+)/$', item.QuestionUpdate.as_view(), name='event.items.questions.edit'),
|
name='event.items.questions.delete'),
|
||||||
|
url(r'^questions/(?P<question>[0-9a-f-]+)/$', item.QuestionUpdate.as_view(),
|
||||||
|
name='event.items.questions.edit'),
|
||||||
url(r'^questions/add$', item.QuestionCreate.as_view(), name='event.items.questions.add'),
|
url(r'^questions/add$', item.QuestionCreate.as_view(), name='event.items.questions.add'),
|
||||||
url(r'^properties/$', item.PropertyList.as_view(), name='event.items.properties'),
|
url(r'^properties/$', item.PropertyList.as_view(), name='event.items.properties'),
|
||||||
url(r'^properties/(?P<property>[0-9a-f-]+)/$', item.PropertyUpdate.as_view(), name='event.items.properties.edit'),
|
url(r'^properties/(?P<property>[0-9a-f-]+)/$', item.PropertyUpdate.as_view(),
|
||||||
url(r'^properties/(?P<property>[0-9a-f-]+)/delete$', item.PropertyDelete.as_view(), name='event.items.properties.delete'),
|
name='event.items.properties.edit'),
|
||||||
|
url(r'^properties/(?P<property>[0-9a-f-]+)/delete$', item.PropertyDelete.as_view(),
|
||||||
|
name='event.items.properties.delete'),
|
||||||
url(r'^properties/add$', item.PropertyCreate.as_view(), name='event.items.properties.add'),
|
url(r'^properties/add$', item.PropertyCreate.as_view(), name='event.items.properties.add'),
|
||||||
url(r'^quotas/$', item.QuotaList.as_view(), name='event.items.quotas'),
|
url(r'^quotas/$', item.QuotaList.as_view(), name='event.items.quotas'),
|
||||||
url(r'^quotas/(?P<quota>[0-9a-f-]+)/$', item.QuotaUpdate.as_view(), name='event.items.quotas.edit'),
|
url(r'^quotas/(?P<quota>[0-9a-f-]+)/$', item.QuotaUpdate.as_view(), name='event.items.quotas.edit'),
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ from django.contrib.auth import logout as auth_logout
|
|||||||
|
|
||||||
class AuthenticationForm(BaseAuthenticationForm):
|
class AuthenticationForm(BaseAuthenticationForm):
|
||||||
"""
|
"""
|
||||||
The login form, providing an email and password field. The
|
The login form, providing an email and password field. The form already implements
|
||||||
form does already implement validation for correct user data.
|
validation for correct user data.
|
||||||
"""
|
"""
|
||||||
email = forms.EmailField(label=_("E-mail address"), max_length=254)
|
email = forms.EmailField(label=_("E-mail address"), max_length=254)
|
||||||
password = forms.CharField(label=_("Password"), widget=forms.PasswordInput)
|
password = forms.CharField(label=_("Password"), widget=forms.PasswordInput)
|
||||||
@@ -68,5 +68,8 @@ def login(request):
|
|||||||
|
|
||||||
|
|
||||||
def logout(request):
|
def logout(request):
|
||||||
|
"""
|
||||||
|
Log the user out of the current session, then redirect to login page.
|
||||||
|
"""
|
||||||
auth_logout(request)
|
auth_logout(request)
|
||||||
return redirect('control:auth.login')
|
return redirect('control:auth.login')
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ class EventPlugins(EventPermissionRequiredMixin, TemplateView, SingleObjectMixin
|
|||||||
permission = 'can_change_settings'
|
permission = 'can_change_settings'
|
||||||
template_name = 'tixlcontrol/event/plugins.html'
|
template_name = 'tixlcontrol/event/plugins.html'
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None) -> Event:
|
||||||
return self.request.event
|
return self.request.event
|
||||||
|
|
||||||
def get_context_data(self, *args, **kwargs) -> dict:
|
def get_context_data(self, *args, **kwargs) -> dict:
|
||||||
|
|||||||
@@ -13,6 +13,14 @@ from tixlbase.models import ItemVariation, PropertyValue, Item
|
|||||||
|
|
||||||
|
|
||||||
class TolerantFormsetModelForm(VersionedModelForm):
|
class TolerantFormsetModelForm(VersionedModelForm):
|
||||||
|
"""
|
||||||
|
This is equivalent to a normal VersionedModelForm, but works around a problem that
|
||||||
|
arises when the form is used inside a FormSet with can_order=True and django-formset-js
|
||||||
|
enabled. In this configuration, even empty "extra" forms might have an ORDER value
|
||||||
|
sent and Django marks the form as empty and raises validation errors because the other
|
||||||
|
fields have not been filled.
|
||||||
|
"""
|
||||||
|
|
||||||
def has_changed(self) -> bool:
|
def has_changed(self) -> bool:
|
||||||
"""
|
"""
|
||||||
Returns True if data differs from initial. Contrary to the default
|
Returns True if data differs from initial. Contrary to the default
|
||||||
@@ -99,6 +107,10 @@ class RestrictionInlineFormset(forms.BaseInlineFormSet):
|
|||||||
|
|
||||||
|
|
||||||
class VariationsFieldRenderer(forms.widgets.CheckboxFieldRenderer):
|
class VariationsFieldRenderer(forms.widgets.CheckboxFieldRenderer):
|
||||||
|
"""
|
||||||
|
This is the default renderer for a VariationsField. Based on the choice input class
|
||||||
|
this renders a list or a matrix of checkboxes/radio buttons/...
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, name, value, attrs, choices):
|
def __init__(self, name, value, attrs, choices):
|
||||||
self.name = name
|
self.name = name
|
||||||
@@ -207,10 +219,17 @@ class VariationsFieldRenderer(forms.widgets.CheckboxFieldRenderer):
|
|||||||
|
|
||||||
|
|
||||||
class VariationsCheckboxRenderer(VariationsFieldRenderer):
|
class VariationsCheckboxRenderer(VariationsFieldRenderer):
|
||||||
|
"""
|
||||||
|
This is the same as VariationsFieldRenderer but with the choice input class
|
||||||
|
forced to checkboxes
|
||||||
|
"""
|
||||||
choice_input_class = forms.widgets.CheckboxChoiceInput
|
choice_input_class = forms.widgets.CheckboxChoiceInput
|
||||||
|
|
||||||
|
|
||||||
class VariationsSelectMultiple(forms.CheckboxSelectMultiple):
|
class VariationsSelectMultiple(forms.CheckboxSelectMultiple):
|
||||||
|
"""
|
||||||
|
This is the default widget for a VariationsField
|
||||||
|
"""
|
||||||
renderer = VariationsCheckboxRenderer
|
renderer = VariationsCheckboxRenderer
|
||||||
_empty_value = []
|
_empty_value = []
|
||||||
|
|
||||||
@@ -240,7 +259,7 @@ class VariationsField(forms.ModelMultipleChoiceField):
|
|||||||
"""
|
"""
|
||||||
We can't use a normal QuerySet as there theoretically might be
|
We can't use a normal QuerySet as there theoretically might be
|
||||||
two types of variations: Some who already have a ItemVariation
|
two types of variations: Some who already have a ItemVariation
|
||||||
object associated with tham and some who don't. We therefore use
|
object associated with them and some who don't. We therefore use
|
||||||
the item's ``get_all_variations`` method. In the first case, we
|
the item's ``get_all_variations`` method. In the first case, we
|
||||||
use the ItemVariation objects primary key as our choice, key,
|
use the ItemVariation objects primary key as our choice, key,
|
||||||
in the latter case we use a string constructed from the values
|
in the latter case we use a string constructed from the values
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ class CategoryDelete(EventPermissionRequiredMixin, DeleteView):
|
|||||||
permission = 'can_change_items'
|
permission = 'can_change_items'
|
||||||
context_object_name = 'category'
|
context_object_name = 'category'
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None) -> ItemCategory:
|
||||||
url = resolve(self.request.path_info)
|
url = resolve(self.request.path_info)
|
||||||
return self.request.event.categories.current.get(
|
return self.request.event.categories.current.get(
|
||||||
identity=url.kwargs['category']
|
identity=url.kwargs['category']
|
||||||
@@ -62,7 +62,7 @@ class CategoryDelete(EventPermissionRequiredMixin, DeleteView):
|
|||||||
self.object.delete()
|
self.object.delete()
|
||||||
return HttpResponseRedirect(success_url)
|
return HttpResponseRedirect(success_url)
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self) -> str:
|
||||||
return reverse('control:event.items.categories', kwargs={
|
return reverse('control:event.items.categories', kwargs={
|
||||||
'organizer': self.request.event.organizer.slug,
|
'organizer': self.request.event.organizer.slug,
|
||||||
'event': self.request.event.slug,
|
'event': self.request.event.slug,
|
||||||
@@ -76,13 +76,13 @@ class CategoryUpdate(EventPermissionRequiredMixin, UpdateView):
|
|||||||
permission = 'can_change_items'
|
permission = 'can_change_items'
|
||||||
context_object_name = 'category'
|
context_object_name = 'category'
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None) -> ItemCategory:
|
||||||
url = resolve(self.request.path_info)
|
url = resolve(self.request.path_info)
|
||||||
return self.request.event.categories.current.get(
|
return self.request.event.categories.current.get(
|
||||||
identity=url.kwargs['category']
|
identity=url.kwargs['category']
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self) -> str:
|
||||||
return reverse('control:event.items.categories', kwargs={
|
return reverse('control:event.items.categories', kwargs={
|
||||||
'organizer': self.request.event.organizer.slug,
|
'organizer': self.request.event.organizer.slug,
|
||||||
'event': self.request.event.slug,
|
'event': self.request.event.slug,
|
||||||
@@ -96,7 +96,7 @@ class CategoryCreate(EventPermissionRequiredMixin, CreateView):
|
|||||||
permission = 'can_change_items'
|
permission = 'can_change_items'
|
||||||
context_object_name = 'category'
|
context_object_name = 'category'
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self) -> str:
|
||||||
return reverse('control:event.items.categories', kwargs={
|
return reverse('control:event.items.categories', kwargs={
|
||||||
'organizer': self.request.event.organizer.slug,
|
'organizer': self.request.event.organizer.slug,
|
||||||
'event': self.request.event.slug,
|
'event': self.request.event.slug,
|
||||||
@@ -116,7 +116,12 @@ class CategoryList(ListView):
|
|||||||
return self.request.event.categories.current.all()
|
return self.request.event.categories.current.all()
|
||||||
|
|
||||||
|
|
||||||
def category_move(request, organizer, event, category, up=True):
|
def category_move(request, category, up=True):
|
||||||
|
"""
|
||||||
|
This is a helper function to avoid duplicating code in category_move_up and
|
||||||
|
category_move_down. It takes a category and a direction and then tries to bring
|
||||||
|
all categories for this event in a new order.
|
||||||
|
"""
|
||||||
category = request.event.categories.current.get(
|
category = request.event.categories.current.get(
|
||||||
identity=category
|
identity=category
|
||||||
)
|
)
|
||||||
@@ -136,7 +141,7 @@ def category_move(request, organizer, event, category, up=True):
|
|||||||
|
|
||||||
@event_permission_required("can_change_items")
|
@event_permission_required("can_change_items")
|
||||||
def category_move_up(request, organizer, event, category):
|
def category_move_up(request, organizer, event, category):
|
||||||
category_move(request, organizer, event, category, up=True)
|
category_move(request, category, up=True)
|
||||||
return redirect(reverse('control:event.items.categories', kwargs={
|
return redirect(reverse('control:event.items.categories', kwargs={
|
||||||
'organizer': request.event.organizer.slug,
|
'organizer': request.event.organizer.slug,
|
||||||
'event': request.event.slug,
|
'event': request.event.slug,
|
||||||
@@ -145,7 +150,7 @@ def category_move_up(request, organizer, event, category):
|
|||||||
|
|
||||||
@event_permission_required("can_change_items")
|
@event_permission_required("can_change_items")
|
||||||
def category_move_down(request, organizer, event, category):
|
def category_move_down(request, organizer, event, category):
|
||||||
category_move(request, organizer, event, category, up=False)
|
category_move(request, category, up=False)
|
||||||
return redirect(reverse('control:event.items.categories', kwargs={
|
return redirect(reverse('control:event.items.categories', kwargs={
|
||||||
'organizer': request.event.organizer.slug,
|
'organizer': request.event.organizer.slug,
|
||||||
'event': request.event.slug,
|
'event': request.event.slug,
|
||||||
@@ -188,13 +193,13 @@ class PropertyUpdate(EventPermissionRequiredMixin, UpdateView):
|
|||||||
permission = 'can_change_items'
|
permission = 'can_change_items'
|
||||||
context_object_name = 'property'
|
context_object_name = 'property'
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None) -> Property:
|
||||||
url = resolve(self.request.path_info)
|
url = resolve(self.request.path_info)
|
||||||
return self.request.event.properties.current.get(
|
return self.request.event.properties.current.get(
|
||||||
identity=url.kwargs['property']
|
identity=url.kwargs['property']
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self) -> str:
|
||||||
url = resolve(self.request.path_info)
|
url = resolve(self.request.path_info)
|
||||||
return reverse('control:event.items.properties.edit', kwargs={
|
return reverse('control:event.items.properties.edit', kwargs={
|
||||||
'organizer': self.request.event.organizer.slug,
|
'organizer': self.request.event.organizer.slug,
|
||||||
@@ -214,7 +219,7 @@ class PropertyUpdate(EventPermissionRequiredMixin, UpdateView):
|
|||||||
formset = formsetclass(**kwargs)
|
formset = formsetclass(**kwargs)
|
||||||
return formset
|
return formset
|
||||||
|
|
||||||
def get_context_data(self, *args, **kwargs):
|
def get_context_data(self, *args, **kwargs) -> dict:
|
||||||
context = super().get_context_data(*args, **kwargs)
|
context = super().get_context_data(*args, **kwargs)
|
||||||
context['formset'] = self.get_formset()
|
context['formset'] = self.get_formset()
|
||||||
return context
|
return context
|
||||||
@@ -249,7 +254,7 @@ class PropertyCreate(EventPermissionRequiredMixin, CreateView):
|
|||||||
permission = 'can_change_items'
|
permission = 'can_change_items'
|
||||||
context_object_name = 'property'
|
context_object_name = 'property'
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self) -> str:
|
||||||
return reverse('control:event.items.properties', kwargs={
|
return reverse('control:event.items.properties', kwargs={
|
||||||
'organizer': self.request.event.organizer.slug,
|
'organizer': self.request.event.organizer.slug,
|
||||||
'event': self.request.event.slug,
|
'event': self.request.event.slug,
|
||||||
@@ -265,7 +270,7 @@ class PropertyCreate(EventPermissionRequiredMixin, CreateView):
|
|||||||
formset = formsetclass(**self.get_form_kwargs())
|
formset = formsetclass(**self.get_form_kwargs())
|
||||||
return formset
|
return formset
|
||||||
|
|
||||||
def get_context_data(self, *args, **kwargs):
|
def get_context_data(self, *args, **kwargs) -> dict:
|
||||||
self.object = None
|
self.object = None
|
||||||
context = super().get_context_data(*args, **kwargs)
|
context = super().get_context_data(*args, **kwargs)
|
||||||
context['formset'] = self.get_formset()
|
context['formset'] = self.get_formset()
|
||||||
@@ -297,16 +302,16 @@ class PropertyDelete(EventPermissionRequiredMixin, DeleteView):
|
|||||||
permission = 'can_change_items'
|
permission = 'can_change_items'
|
||||||
context_object_name = 'property'
|
context_object_name = 'property'
|
||||||
|
|
||||||
def get_context_data(self, *args, **kwargs):
|
def get_context_data(self, *args, **kwargs) -> dict:
|
||||||
context = super().get_context_data(*args, **kwargs)
|
context = super().get_context_data(*args, **kwargs)
|
||||||
context['dependent'] = self.get_object().items.current.all()
|
context['dependent'] = self.get_object().items.current.all()
|
||||||
context['possible'] = self.is_allowed()
|
context['possible'] = self.is_allowed()
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def is_allowed(self):
|
def is_allowed(self) -> bool:
|
||||||
return self.get_object().items.current.count() == 0
|
return self.get_object().items.current.count() == 0
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None) -> Property:
|
||||||
if not hasattr(self, 'object') or not self.object:
|
if not hasattr(self, 'object') or not self.object:
|
||||||
url = resolve(self.request.path_info)
|
url = resolve(self.request.path_info)
|
||||||
self.object = self.request.event.properties.current.get(
|
self.object = self.request.event.properties.current.get(
|
||||||
@@ -322,7 +327,7 @@ class PropertyDelete(EventPermissionRequiredMixin, DeleteView):
|
|||||||
else:
|
else:
|
||||||
return HttpResponseForbidden()
|
return HttpResponseForbidden()
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self) -> str:
|
||||||
return reverse('control:event.items.properties', kwargs={
|
return reverse('control:event.items.properties', kwargs={
|
||||||
'organizer': self.request.event.organizer.slug,
|
'organizer': self.request.event.organizer.slug,
|
||||||
'event': self.request.event.slug,
|
'event': self.request.event.slug,
|
||||||
@@ -356,13 +361,13 @@ class QuestionDelete(EventPermissionRequiredMixin, DeleteView):
|
|||||||
permission = 'can_change_items'
|
permission = 'can_change_items'
|
||||||
context_object_name = 'question'
|
context_object_name = 'question'
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None) -> Question:
|
||||||
url = resolve(self.request.path_info)
|
url = resolve(self.request.path_info)
|
||||||
return self.request.event.questions.current.get(
|
return self.request.event.questions.current.get(
|
||||||
identity=url.kwargs['question']
|
identity=url.kwargs['question']
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_context_data(self, *args, **kwargs):
|
def get_context_data(self, *args, **kwargs) -> dict:
|
||||||
context = super().get_context_data(*args, **kwargs)
|
context = super().get_context_data(*args, **kwargs)
|
||||||
context['dependent'] = list(self.get_object().items.current.all())
|
context['dependent'] = list(self.get_object().items.current.all())
|
||||||
return context
|
return context
|
||||||
@@ -373,7 +378,7 @@ class QuestionDelete(EventPermissionRequiredMixin, DeleteView):
|
|||||||
self.object.delete()
|
self.object.delete()
|
||||||
return HttpResponseRedirect(success_url)
|
return HttpResponseRedirect(success_url)
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self) -> str:
|
||||||
return reverse('control:event.items.questions', kwargs={
|
return reverse('control:event.items.questions', kwargs={
|
||||||
'organizer': self.request.event.organizer.slug,
|
'organizer': self.request.event.organizer.slug,
|
||||||
'event': self.request.event.slug,
|
'event': self.request.event.slug,
|
||||||
@@ -387,13 +392,13 @@ class QuestionUpdate(EventPermissionRequiredMixin, UpdateView):
|
|||||||
permission = 'can_change_items'
|
permission = 'can_change_items'
|
||||||
context_object_name = 'question'
|
context_object_name = 'question'
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None) -> Question:
|
||||||
url = resolve(self.request.path_info)
|
url = resolve(self.request.path_info)
|
||||||
return self.request.event.questions.current.get(
|
return self.request.event.questions.current.get(
|
||||||
identity=url.kwargs['question']
|
identity=url.kwargs['question']
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self) -> str:
|
||||||
return reverse('control:event.items.questions', kwargs={
|
return reverse('control:event.items.questions', kwargs={
|
||||||
'organizer': self.request.event.organizer.slug,
|
'organizer': self.request.event.organizer.slug,
|
||||||
'event': self.request.event.slug,
|
'event': self.request.event.slug,
|
||||||
@@ -407,7 +412,7 @@ class QuestionCreate(EventPermissionRequiredMixin, CreateView):
|
|||||||
permission = 'can_change_items'
|
permission = 'can_change_items'
|
||||||
context_object_name = 'question'
|
context_object_name = 'question'
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self) -> str:
|
||||||
return reverse('control:event.items.questions', kwargs={
|
return reverse('control:event.items.questions', kwargs={
|
||||||
'organizer': self.request.event.organizer.slug,
|
'organizer': self.request.event.organizer.slug,
|
||||||
'event': self.request.event.slug,
|
'event': self.request.event.slug,
|
||||||
@@ -447,7 +452,7 @@ class QuotaCreate(EventPermissionRequiredMixin, CreateView):
|
|||||||
permission = 'can_change_items'
|
permission = 'can_change_items'
|
||||||
context_object_name = 'quota'
|
context_object_name = 'quota'
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self) -> str:
|
||||||
return reverse('control:event.items.quotas', kwargs={
|
return reverse('control:event.items.quotas', kwargs={
|
||||||
'organizer': self.request.event.organizer.slug,
|
'organizer': self.request.event.organizer.slug,
|
||||||
'event': self.request.event.slug,
|
'event': self.request.event.slug,
|
||||||
@@ -465,13 +470,13 @@ class QuotaUpdate(EventPermissionRequiredMixin, UpdateView):
|
|||||||
permission = 'can_change_items'
|
permission = 'can_change_items'
|
||||||
context_object_name = 'quota'
|
context_object_name = 'quota'
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None) -> Quota:
|
||||||
url = resolve(self.request.path_info)
|
url = resolve(self.request.path_info)
|
||||||
return self.request.event.quotas.current.get(
|
return self.request.event.quotas.current.get(
|
||||||
identity=url.kwargs['quota']
|
identity=url.kwargs['quota']
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self) -> str:
|
||||||
return reverse('control:event.items.quotas', kwargs={
|
return reverse('control:event.items.quotas', kwargs={
|
||||||
'organizer': self.request.event.organizer.slug,
|
'organizer': self.request.event.organizer.slug,
|
||||||
'event': self.request.event.slug,
|
'event': self.request.event.slug,
|
||||||
@@ -484,13 +489,13 @@ class QuotaDelete(EventPermissionRequiredMixin, DeleteView):
|
|||||||
permission = 'can_change_items'
|
permission = 'can_change_items'
|
||||||
context_object_name = 'quota'
|
context_object_name = 'quota'
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None) -> Quota:
|
||||||
url = resolve(self.request.path_info)
|
url = resolve(self.request.path_info)
|
||||||
return self.request.event.quotas.current.get(
|
return self.request.event.quotas.current.get(
|
||||||
identity=url.kwargs['quota']
|
identity=url.kwargs['quota']
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_context_data(self, *args, **kwargs):
|
def get_context_data(self, *args, **kwargs) -> dict:
|
||||||
context = super().get_context_data(*args, **kwargs)
|
context = super().get_context_data(*args, **kwargs)
|
||||||
context['dependent'] = list(self.get_object().items.current.all())
|
context['dependent'] = list(self.get_object().items.current.all())
|
||||||
return context
|
return context
|
||||||
@@ -501,7 +506,7 @@ class QuotaDelete(EventPermissionRequiredMixin, DeleteView):
|
|||||||
self.object.delete()
|
self.object.delete()
|
||||||
return HttpResponseRedirect(success_url)
|
return HttpResponseRedirect(success_url)
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self) -> str:
|
||||||
return reverse('control:event.items.quotas', kwargs={
|
return reverse('control:event.items.quotas', kwargs={
|
||||||
'organizer': self.request.event.organizer.slug,
|
'organizer': self.request.event.organizer.slug,
|
||||||
'event': self.request.event.slug,
|
'event': self.request.event.slug,
|
||||||
@@ -512,7 +517,7 @@ class ItemDetailMixin(SingleObjectMixin):
|
|||||||
model = Item
|
model = Item
|
||||||
context_object_name = 'item'
|
context_object_name = 'item'
|
||||||
|
|
||||||
def get_object(self, queryset=None):
|
def get_object(self, queryset=None) -> Item:
|
||||||
if not hasattr(self, 'object') or not self.object:
|
if not hasattr(self, 'object') or not self.object:
|
||||||
url = resolve(self.request.path_info)
|
url = resolve(self.request.path_info)
|
||||||
self.item = self.request.event.items.current.get(
|
self.item = self.request.event.items.current.get(
|
||||||
@@ -551,7 +556,7 @@ class ItemUpdateGeneral(ItemDetailMixin, EventPermissionRequiredMixin, UpdateVie
|
|||||||
template_name = 'tixlcontrol/item/index.html'
|
template_name = 'tixlcontrol/item/index.html'
|
||||||
permission = 'can_change_items'
|
permission = 'can_change_items'
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self) -> str:
|
||||||
return reverse('control:event.item', kwargs={
|
return reverse('control:event.item', kwargs={
|
||||||
'organizer': self.request.event.organizer.slug,
|
'organizer': self.request.event.organizer.slug,
|
||||||
'event': self.request.event.slug,
|
'event': self.request.event.slug,
|
||||||
@@ -578,7 +583,7 @@ class ItemVariations(ItemDetailMixin, EventPermissionRequiredMixin, TemplateView
|
|||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.item = None
|
self.item = None
|
||||||
|
|
||||||
def get_form(self, variation, data=None):
|
def get_form(self, variation, data=None) -> ItemVariationForm:
|
||||||
"""
|
"""
|
||||||
Return the dict for one given variation. Variations are expected to be
|
Return the dict for one given variation. Variations are expected to be
|
||||||
dictionaries in the format of Item.get_all_variations()
|
dictionaries in the format of Item.get_all_variations()
|
||||||
@@ -603,7 +608,7 @@ class ItemVariations(ItemDetailMixin, EventPermissionRequiredMixin, TemplateView
|
|||||||
form.values = values
|
form.values = values
|
||||||
return form
|
return form
|
||||||
|
|
||||||
def get_forms(self):
|
def get_forms(self) -> tuple:
|
||||||
"""
|
"""
|
||||||
Returns one form per possible item variation. The forms are returned
|
Returns one form per possible item variation. The forms are returned
|
||||||
twice: The first entry in the returned tuple contains a 1-, 2- or
|
twice: The first entry in the returned tuple contains a 1-, 2- or
|
||||||
@@ -705,7 +710,7 @@ class ItemVariations(ItemDetailMixin, EventPermissionRequiredMixin, TemplateView
|
|||||||
# TODO: Redirect to success message
|
# TODO: Redirect to success message
|
||||||
return self.render_to_response(context)
|
return self.render_to_response(context)
|
||||||
|
|
||||||
def get_template_names(self):
|
def get_template_names(self) -> "List[str]":
|
||||||
if self.dimension == 0:
|
if self.dimension == 0:
|
||||||
return ['tixlcontrol/item/variations_0d.html']
|
return ['tixlcontrol/item/variations_0d.html']
|
||||||
elif self.dimension == 1:
|
elif self.dimension == 1:
|
||||||
@@ -713,7 +718,7 @@ class ItemVariations(ItemDetailMixin, EventPermissionRequiredMixin, TemplateView
|
|||||||
elif self.dimension >= 2:
|
elif self.dimension >= 2:
|
||||||
return ['tixlcontrol/item/variations_nd.html']
|
return ['tixlcontrol/item/variations_nd.html']
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs) -> dict:
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context['forms'] = self.forms
|
context['forms'] = self.forms
|
||||||
context['properties'] = self.properties
|
context['properties'] = self.properties
|
||||||
@@ -768,12 +773,12 @@ class ItemRestrictions(ItemDetailMixin, EventPermissionRequiredMixin, TemplateVi
|
|||||||
context = self.get_context_data(object=self.object)
|
context = self.get_context_data(object=self.object)
|
||||||
return self.render_to_response(context)
|
return self.render_to_response(context)
|
||||||
|
|
||||||
def get_context_data(self, *args, **kwargs):
|
def get_context_data(self, *args, **kwargs) -> dict:
|
||||||
context = super().get_context_data(*args, **kwargs)
|
context = super().get_context_data(*args, **kwargs)
|
||||||
context['formsets'] = self.formsets
|
context['formsets'] = self.formsets
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_success_url(self):
|
def get_success_url(self) -> str:
|
||||||
return reverse('control:event.item.restrictions', kwargs={
|
return reverse('control:event.item.restrictions', kwargs={
|
||||||
'organizer': self.request.event.organizer.slug,
|
'organizer': self.request.event.organizer.slug,
|
||||||
'event': self.request.event.slug,
|
'event': self.request.event.slug,
|
||||||
|
|||||||
Reference in New Issue
Block a user