mirror of
https://github.com/pretix/pretix.git
synced 2026-05-05 15:14:04 +00:00
Manage variations for items with exactly one property
This commit is contained in:
@@ -538,9 +538,10 @@ class ItemVariation(models.Model):
|
||||
)
|
||||
active = models.BooleanField(
|
||||
default=True,
|
||||
verbose_name=_("Active"),
|
||||
)
|
||||
default_price = models.DecimalField(
|
||||
decimal_places=2, max_digits=7,
|
||||
null=True, blank=True,
|
||||
verbose_name=_("Default price")
|
||||
verbose_name=_("Default price"),
|
||||
)
|
||||
|
||||
16
src/tixlcontrol/static/tixlcontrol/less/forms.less
Normal file
16
src/tixlcontrol/static/tixlcontrol/less/forms.less
Normal file
@@ -0,0 +1,16 @@
|
||||
td > .form-group {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
td > .errorlist {
|
||||
color: #a94442;
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
td > .form-group > .checkbox {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.has-success .form-control {
|
||||
border-color: #cccccc;
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
@import "../../../../tixlbase/static/bootstrap/less/bootstrap.less";
|
||||
@import "../../../../tixlbase/static/fontawesome/less/font-awesome.less";
|
||||
@fa-font-path: "../../fontawesome/fonts";
|
||||
@import "forms.less";
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<h1>{% trans "Modify item:" %} {{ item.name }}</h1>
|
||||
<ul class="nav nav-pills">
|
||||
<li {% if "event.item" == url_name %}class="active"{% endif %}><a href="{% url 'control:event.item' organizer=request.event.organizer.slug event=request.event.slug item=item.pk %}">{% trans "General information" %}</a></li>
|
||||
<li {% if "event.item.variations" == url_name %}class="active"{% endif %}><a href="{% url 'control:event.item.variations' organizer=request.event.organizer.slug event=request.event.slug item=item.pk %}">{% trans "Variations" %}</a></li>
|
||||
</ul>
|
||||
{% block inside %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
{% extends "tixlcontrol/item/base.html" %}
|
||||
{% load i18n %}
|
||||
{% load bootstrap3 %}
|
||||
{% block inside %}
|
||||
<h2>{% trans "Variations" %}</h2>
|
||||
<form action="" method="post">
|
||||
{% csrf_token %}
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ properties.0 }}</th>
|
||||
<th>{% trans "Active" %}</th>
|
||||
<th>{% trans "Price" %}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for form in forms %}
|
||||
{% bootstrap_form_errors form type='all' layout='inline' %}
|
||||
<tr>
|
||||
<td>{{ form.values.0 }}</td>
|
||||
<td>{% bootstrap_field form.active layout='inline' %}</td>
|
||||
<td>{% bootstrap_field form.default_price layout='inline' %} {{ form.default_price.errors }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-12">
|
||||
<button type="submit" class="btn btn-primary">
|
||||
{% trans "Save" %}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{% endblock %}
|
||||
@@ -21,6 +21,7 @@ urlpatterns += patterns(
|
||||
url(r'^settings$', event.EventUpdate.as_view(), name='event.settings'),
|
||||
url(r'^items$', item.ItemList.as_view(), name='event.items'),
|
||||
url(r'^items/(?P<item>\d+)/$', item.ItemUpdateGeneral.as_view(), name='event.item'),
|
||||
url(r'^items/(?P<item>\d+)/variations$', item.ItemVariations.as_view(), name='event.item.variations'),
|
||||
url(r'^categories$', item.CategoryList.as_view(), name='event.items.categories'),
|
||||
url(r'^properties$', item.PropertyList.as_view(), name='event.items.properties'),
|
||||
)
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
from django.views.generic import ListView
|
||||
from django.views.generic.edit import UpdateView
|
||||
from django.views.generic.base import TemplateView
|
||||
from django.views.generic.detail import SingleObjectMixin
|
||||
from django.core.urlresolvers import resolve, reverse
|
||||
from django import forms
|
||||
|
||||
from tixlbase.models import Item, ItemCategory, Property
|
||||
from tixlbase.models import Item, ItemCategory, Property, ItemVariation
|
||||
from tixlcontrol.permissions import EventPermissionRequiredMixin
|
||||
|
||||
|
||||
@@ -81,3 +83,97 @@ class ItemUpdateGeneral(EventPermissionRequiredMixin, UpdateView):
|
||||
'event': self.request.event.slug,
|
||||
'item': self.get_object().pk,
|
||||
}) + '?success=true'
|
||||
|
||||
|
||||
class ItemVariationForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = ItemVariation
|
||||
localized_fields = '__all__'
|
||||
fields = [
|
||||
'active',
|
||||
'default_price',
|
||||
]
|
||||
|
||||
|
||||
class ItemVariations(TemplateView, SingleObjectMixin):
|
||||
|
||||
model = Item
|
||||
context_object_name = 'item'
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.item = None
|
||||
|
||||
def get_forms(self):
|
||||
"""
|
||||
Returns one form per possible item variation. The forms are returned
|
||||
twice: The first entry in the returned tuple contains a 1-, 2- or
|
||||
3-dimensional list, depending on the number of properties associated
|
||||
with this item (this is being used for form display), the second
|
||||
contains all forms in one single list (this is used for processing).
|
||||
"""
|
||||
forms = []
|
||||
forms_flat = []
|
||||
variations = self.object.get_all_variations()
|
||||
data = self.request.POST if self.request.method == 'POST' else None
|
||||
if self.dimension == 1:
|
||||
for var in variations:
|
||||
val = [i[1] for i in sorted([it for it in var.items() if it[0] != 'variation'])]
|
||||
if 'variation' in var:
|
||||
form = ItemVariationForm(
|
||||
data,
|
||||
instance=var['variation'],
|
||||
prefix=",".join([str(i) for i in val])
|
||||
)
|
||||
else:
|
||||
form = ItemVariationForm(
|
||||
data,
|
||||
instance=ItemVariation(item=self.object),
|
||||
prefix=",".join([str(i) for i in val])
|
||||
)
|
||||
form.values = val
|
||||
forms.append(form)
|
||||
forms_flat = forms
|
||||
return forms, forms_flat
|
||||
|
||||
def main(self, request, *args, **kwargs):
|
||||
self.object = self.get_object()
|
||||
self.properties = self.object.properties.all()
|
||||
self.dimension = self.properties.count()
|
||||
self.forms, self.forms_flat = self.get_forms()
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
self.main(request, *args, **kwargs)
|
||||
context = self.get_context_data(object=self.object)
|
||||
return self.render_to_response(context)
|
||||
|
||||
def post(self, request, *args, **kwargs):
|
||||
self.main(request, *args, **kwargs)
|
||||
context = self.get_context_data(object=self.object)
|
||||
for form in self.forms_flat:
|
||||
if form.is_valid():
|
||||
if form.instance.pk is None:
|
||||
form.save()
|
||||
form.instance.values.add(*form.values)
|
||||
else:
|
||||
form.save()
|
||||
return self.render_to_response(context)
|
||||
|
||||
def get_object(self, queryset=None):
|
||||
if not self.item:
|
||||
url = resolve(self.request.path_info)
|
||||
self.item = self.request.event.items.get(
|
||||
id=url.kwargs['item']
|
||||
)
|
||||
return self.item
|
||||
|
||||
def get_template_names(self):
|
||||
if self.dimension == 1:
|
||||
return ['tixlcontrol/item/variations_1d.html']
|
||||
|
||||
def get_context_data(self, **kwargs):
|
||||
context = super().get_context_data(**kwargs)
|
||||
context['forms'] = self.forms
|
||||
context['properties'] = self.properties
|
||||
return context
|
||||
|
||||
Reference in New Issue
Block a user