Refs #102 -- Added multiple-choice question types

This commit is contained in:
Raphael Michel
2016-02-23 10:09:33 +01:00
parent eed74545bc
commit 1cd0c1f53b
12 changed files with 306 additions and 25 deletions

View File

@@ -5,8 +5,9 @@ from django.forms import BooleanField, ModelMultipleChoiceField
from django.utils.translation import ugettext as __, ugettext_lazy as _
from pretix.base.forms import I18nModelForm
from pretix.base.i18n import I18nFormField, I18nTextarea
from pretix.base.models import (
Item, ItemCategory, ItemVariation, Question, Quota,
Item, ItemCategory, ItemVariation, Question, QuestionOption, Quota,
)
@@ -20,6 +21,12 @@ class CategoryForm(I18nModelForm):
class QuestionForm(I18nModelForm):
question = I18nFormField(
label=_("Question"),
widget_kwargs={'attrs': {'rows': 5}},
widget=I18nTextarea
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['items'].queryset = self.instance.event.items.all()
@@ -34,10 +41,20 @@ class QuestionForm(I18nModelForm):
'items'
]
widgets = {
'items': forms.CheckboxSelectMultiple
'items': forms.CheckboxSelectMultiple,
}
class QuestionOptionForm(I18nModelForm):
class Meta:
model = QuestionOption
localized_fields = '__all__'
fields = [
'answer',
]
class QuotaForm(I18nModelForm):
def __init__(self, **kwargs):

View File

@@ -1,6 +1,7 @@
{% extends "pretixcontrol/items/base.html" %}
{% load i18n %}
{% load bootstrap3 %}
{% load formset_tags %}
{% block title %}{% trans "Question" %}{% endblock %}
{% block inside %}
<h1>{% trans "Question" %}</h1>
@@ -23,6 +24,59 @@
accepted. If you want to allow both options, do not make this field required.
{% endblocktrans %}
</div>
<fieldset id="answer-options">
<legend>{% trans "Answer options" %}</legend>
<noscript>
<p>{% trans "Only applicable if you choose 'Choose one/multiple from a list' above." %}</p>
</noscript>
<div class="formset" data-formset data-formset-prefix="{{ formset.prefix }}">
{{ formset.management_form }}
{% bootstrap_formset_errors formset %}
<div data-formset-body>
{% for form in formset %}
<div data-formset-form>
<div class="sr-only">
{{ form.id }}
{% bootstrap_field form.DELETE form_group_class="" layout="inline" %}
</div>
<div class="row question-option-row">
<div class="col-xs-10">
{% bootstrap_form_errors form %}
{% bootstrap_field form.answer layout='inline' form_group_class="" %}
</div>
<div class="col-xs-2 text-right">
<button type="button" class="btn btn-danger" data-formset-delete-button>
<i class="fa fa-trash"></i></button>
</div>
</div>
</div>
{% endfor %}
</div>
<script type="form-template" data-formset-empty-form>
{% escapescript %}
<div data-formset-form>
<div class="sr-only">
{{ formset.empty_form.id }}
{% bootstrap_field formset.empty_form.DELETE form_group_class="" layout="inline" %}
</div>
<div class="row question-option-row">
<div class="col-xs-10">
{% bootstrap_field formset.empty_form.answer layout='inline' form_group_class="" %}
</div>
<div class="col-xs-2 text-right">
<button type="button" class="btn btn-danger" data-formset-delete-button>
<i class="fa fa-trash"></i></button>
</div>
</div>
</div>
{% endescapescript %}
</script>
<p>
<button type="button" class="btn btn-default" data-formset-add>
<i class="fa fa-plus"></i> {% trans "Add a new option" %}</button>
</p>
</div>
</fieldset>
<div class="form-group submit-group">
<button type="submit" class="btn btn-primary btn-save">
{% trans "Save" %}
@@ -31,14 +85,17 @@
</form>
<script type="text/javascript">
$(function () {
function alert_required_boolean() {
var show = $("#id_type").val() == "B" && $("#id_required").prop("checked");
function toggle_view() {
var show = $("#id_type").val() == "C" || $("#id_type").val() == "M";
$("#answer-options").toggle(show);
show = $("#id_type").val() == "B" && $("#id_required").prop("checked");
$(".alert-required-boolean").toggle(show);
}
$("#id_type").change(alert_required_boolean);
$("#id_required").change(alert_required_boolean);
alert_required_boolean();
$("#id_type").change(toggle_view);
$("#id_required").change(toggle_view);
toggle_view();
});
</script>
{% endblock %}

View File

@@ -14,11 +14,11 @@ from django.views.generic.edit import DeleteView
from pretix.base.i18n import I18nFormSet
from pretix.base.models import (
Item, ItemCategory, ItemVariation, Question, Quota,
Item, ItemCategory, ItemVariation, Question, QuestionOption, Quota,
)
from pretix.control.forms.item import (
CategoryForm, ItemCreateForm, ItemFormGeneral, ItemVariationForm,
QuestionForm, QuotaForm,
QuestionForm, QuestionOptionForm, QuotaForm,
)
from pretix.control.permissions import (
EventPermissionRequiredMixin, event_permission_required,
@@ -272,7 +272,67 @@ class QuestionDelete(EventPermissionRequiredMixin, DeleteView):
})
class QuestionUpdate(EventPermissionRequiredMixin, UpdateView):
class QuestionMixin:
@cached_property
def formset(self):
formsetclass = inlineformset_factory(
Question, QuestionOption,
form=QuestionOptionForm, formset=I18nFormSet,
can_order=False, can_delete=True, extra=0
)
return formsetclass(self.request.POST if self.request.method == "POST" else None,
queryset=(QuestionOption.objects.filter(question=self.get_object())
if self.get_object() else QuestionOption.objects.none()),
event=self.request.event)
def save_formset(self, obj):
if self.formset.is_valid():
for form in self.formset.initial_forms:
if form in self.formset.deleted_forms:
if not form.instance.pk:
continue
self.get_object().log_action(
'pretix.event.question.option.deleted', user=self.request.user, data={
'id': form.instance.pk
}
)
form.instance.delete()
form.instance.pk = None
elif form.has_changed():
form.instance.question = self.get_object()
form.save()
change_data = {k: form.cleaned_data.get(k) for k in form.changed_data}
change_data['id'] = form.instance.pk
self.get_object().log_action(
'pretix.event.question.option.changed',
user=self.request.user, data=change_data
)
for form in self.formset.extra_forms:
if not form.has_changed():
continue
if self.formset._should_delete_form(form):
continue
form.instance.question = self.get_object()
form.save()
change_data = {k: form.cleaned_data.get(k) for k in form.changed_data}
change_data['id'] = form.instance.pk
self.get_object().log_action(
'pretix.event.question.option.added',
user=self.request.user, data=change_data
)
return True
return False
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx['formset'] = self.formset
return ctx
class QuestionUpdate(EventPermissionRequiredMixin, QuestionMixin, UpdateView):
model = Question
form_class = QuestionForm
template_name = 'pretixcontrol/items/question.html'
@@ -289,6 +349,10 @@ class QuestionUpdate(EventPermissionRequiredMixin, UpdateView):
@transaction.atomic()
def form_valid(self, form):
if form.cleaned_data.get('type') in ('M', 'C'):
if not self.save_formset(self.get_object):
return self.get(self.request, *self.args, **self.kwargs)
if form.has_changed():
self.object.log_action(
'pretix.event.question.changed', user=self.request.user, data={
@@ -305,7 +369,7 @@ class QuestionUpdate(EventPermissionRequiredMixin, UpdateView):
})
class QuestionCreate(EventPermissionRequiredMixin, CreateView):
class QuestionCreate(EventPermissionRequiredMixin, QuestionMixin, CreateView):
model = Question
form_class = QuestionForm
template_name = 'pretixcontrol/items/question.html'
@@ -323,11 +387,19 @@ class QuestionCreate(EventPermissionRequiredMixin, CreateView):
'event': self.request.event.slug,
})
def get_object(self):
return None
@transaction.atomic()
def form_valid(self, form):
if form.cleaned_data.get('type') in ('M', 'C'):
if not self.save_formset(self.get_object):
return self.get(self.request, *self.args, **self.kwargs)
messages.success(self.request, _('The new question has been created.'))
ret = super().form_valid(form)
form.instance.log_action('pretix.event.question.added', user=self.request.user, data=dict(form.cleaned_data))
self.save_formset(form.instance)
return ret