forked from CGM_Public/pretix_original
Bootstrap the form magic for inline restriction formset variation
controls
This commit is contained in:
@@ -213,4 +213,83 @@ In our example, the implementation could look like this::
|
||||
If you do not copy down to the ``dict`` objects, you will run into
|
||||
interference problems with other plugins.
|
||||
|
||||
Control interface formsets
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To make it possible for the event organizer to configure your restriction, there is a
|
||||
'Restrictions' page in the item configuration. This page is able to show a formset for
|
||||
each restriction plugin, but *you* are required to create this formset. This is why you
|
||||
should listen to the the ``tixlcontrol.signals.restriction_formset`` signal.
|
||||
|
||||
Currently, the signal comes with only one keyword argument:
|
||||
|
||||
``item``
|
||||
The instance of ``tixlbase.models.Item`` we want a formset for.
|
||||
|
||||
You are expected to return a dict containing the following items:
|
||||
|
||||
``formsetclass``
|
||||
An inline formset class (not a formset object).
|
||||
|
||||
``prefix``
|
||||
A unique prefix for your queryset.
|
||||
|
||||
``title``
|
||||
A title for your formset (normally your plugin name)
|
||||
|
||||
|
||||
Our time restriction example looks like this::
|
||||
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django.dispatch import receiver
|
||||
from django.forms.models import inlineformset_factory
|
||||
|
||||
from tixlcontrol.signals import restriction_formset
|
||||
from tixlbase.models import Item
|
||||
from tixlcontrol.views.forms import (
|
||||
VariationsField, RestrictionInlineFormset, RestrictionForm
|
||||
)
|
||||
|
||||
from .models import TimeRestriction
|
||||
|
||||
class TimeRestrictionForm(RestrictionForm):
|
||||
|
||||
class Meta:
|
||||
model = TimeRestriction
|
||||
localized_fields = '__all__'
|
||||
fields = [
|
||||
'variations',
|
||||
'timeframe_from',
|
||||
'timeframe_to',
|
||||
'price',
|
||||
]
|
||||
|
||||
|
||||
@receiver(restriction_formset)
|
||||
def formset_handler(sender, **kwargs):
|
||||
formset = inlineformset_factory(
|
||||
Item,
|
||||
TimeRestriction,
|
||||
formset=RestrictionInlineFormset,
|
||||
form=TimeRestrictionForm,
|
||||
can_order=False,
|
||||
can_delete=True,
|
||||
extra=0,
|
||||
)
|
||||
|
||||
return {
|
||||
'title': _('Restriction by time'),
|
||||
'formsetclass': formset,
|
||||
'prefix': 'timerestriction',
|
||||
}
|
||||
|
||||
|
||||
.. NOTE::
|
||||
If you do use the ``RestrictionInlineFormset``, ``RestrictionForm`` and
|
||||
``VariationsField`` classes in your implementation, we will do a lot of magic for you
|
||||
to display the ``variations`` field in the form in a nice and consistent way. So please,
|
||||
use these base classes and test carefully, if you make any changes to the behaviour
|
||||
of this field.
|
||||
|
||||
|
||||
.. _caching feature: https://docs.djangoproject.com/en/1.7/topics/cache/
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<script type="form-template" data-formset-empty-form>
|
||||
{% escapescript %}
|
||||
<div class="form-horizontal" data-formset-form>
|
||||
{% bootstrap_form set.formset.empty_form layout="horizontal" %}
|
||||
{% bootstrap_form set.formset.initialized_empty_form layout="horizontal" %}
|
||||
</div>
|
||||
{% endescapescript %}
|
||||
</script>
|
||||
|
||||
@@ -30,3 +30,48 @@ class TolerantFormsetModelForm(forms.ModelForm):
|
||||
if field._has_changed(initial_value, data_value):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class RestrictionForm(forms.ModelForm):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
if 'item' in kwargs:
|
||||
self.item = kwargs['item']
|
||||
del kwargs['item']
|
||||
super().__init__(*args, **kwargs)
|
||||
if 'variations' in self.fields:
|
||||
self.fields['variations'] = VariationsField(item=self.item)
|
||||
|
||||
|
||||
class RestrictionInlineFormset(forms.BaseInlineFormSet):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
def initialized_empty_form(self):
|
||||
form = self.form(
|
||||
auto_id=self.auto_id,
|
||||
prefix=self.add_prefix('__prefix__'),
|
||||
empty_permitted=True,
|
||||
item=self.instance
|
||||
)
|
||||
return form
|
||||
|
||||
def _construct_form(self, i, **kwargs):
|
||||
kwargs['item'] = self.instance
|
||||
return super()._construct_form(i, **kwargs)
|
||||
|
||||
|
||||
class VariationsField(forms.ModelMultipleChoiceField):
|
||||
|
||||
def __init__(self, item=None, **kwargs):
|
||||
self.item = item
|
||||
super().__init__(self, **kwargs)
|
||||
|
||||
def _get_choices(self):
|
||||
if not hasattr(self, 'item'):
|
||||
return ()
|
||||
print(self.item.pk)
|
||||
return ()
|
||||
|
||||
choices = property(_get_choices, forms.ChoiceField._set_choices)
|
||||
|
||||
@@ -649,7 +649,7 @@ class ItemRestrictions(ItemDetailMixin, EventPermissionRequiredMixin, TemplateVi
|
||||
for receiver, response in responses:
|
||||
response['formset'] = response['formsetclass'](
|
||||
self.request.POST if self.request.method == 'POST' else None,
|
||||
queryset=response['queryset'],
|
||||
instance=self.object,
|
||||
prefix=response['prefix'],
|
||||
)
|
||||
formsets.append(response)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
from django.dispatch import receiver
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
from django import forms
|
||||
from django.forms.models import modelformset_factory
|
||||
from django.forms.models import inlineformset_factory
|
||||
|
||||
from tixlbase.signals import determine_availability
|
||||
from tixlbase.models import Item
|
||||
from tixlcontrol.views.forms import VariationsField, RestrictionInlineFormset, RestrictionForm
|
||||
from tixlcontrol.signals import restriction_formset
|
||||
|
||||
from .models import TimeRestriction
|
||||
@@ -111,11 +112,13 @@ def availability_handler(sender, **kwargs):
|
||||
return variations
|
||||
|
||||
|
||||
class TimeRestrictionForm(forms.ModelForm):
|
||||
class TimeRestrictionForm(RestrictionForm):
|
||||
|
||||
class Meta:
|
||||
model = TimeRestriction
|
||||
localized_fields = '__all__'
|
||||
fields = [
|
||||
'variations',
|
||||
'timeframe_from',
|
||||
'timeframe_to',
|
||||
'price',
|
||||
@@ -124,21 +127,18 @@ class TimeRestrictionForm(forms.ModelForm):
|
||||
|
||||
@receiver(restriction_formset)
|
||||
def formset_handler(sender, **kwargs):
|
||||
# Handle the signal's input arguments
|
||||
item = kwargs['item']
|
||||
|
||||
formset = modelformset_factory(
|
||||
formset = inlineformset_factory(
|
||||
Item,
|
||||
TimeRestriction,
|
||||
formset=RestrictionInlineFormset,
|
||||
form=TimeRestrictionForm,
|
||||
can_order=False,
|
||||
can_delete=True,
|
||||
extra=0,
|
||||
)
|
||||
queryset = TimeRestriction.objects.filter(item=item)
|
||||
|
||||
return {
|
||||
'title': _('Restriction by time'),
|
||||
'formsetclass': formset,
|
||||
'queryset': queryset,
|
||||
'prefix': 'timerestriction',
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user