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

@@ -225,10 +225,10 @@ class I18nFormField(forms.MultiValueField):
'max_length': kwargs.pop('max_length', None),
}
self.langcodes = kwargs.pop('langcodes', [l[0] for l in settings.LANGUAGES])
self.one_required = kwargs['required']
self.one_required = kwargs.get('required', True)
kwargs['required'] = False
kwargs['widget'] = kwargs['widget'](
langcodes=self.langcodes, field=self
langcodes=self.langcodes, field=self, **kwargs.pop('widget_kwargs', {})
)
defaults.update(**kwargs)
for lngcode in self.langcodes:

View File

@@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.2 on 2016-03-26 11:04
from __future__ import unicode_literals
import django.db.models.deletion
from django.db import migrations, models
import pretix.base.i18n
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0017_auto_20160324_1615'),
]
operations = [
migrations.CreateModel(
name='QuestionOption',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('answer', pretix.base.i18n.I18nCharField(verbose_name='Answer')),
],
),
migrations.AlterField(
model_name='item',
name='free_price',
field=models.BooleanField(default=False, help_text='If this option is active, your users can choose the price themselves. The price configured above is then interpreted as the minimum price a user has to enter. You could use this e.g. to collect additional donations for your event.', verbose_name='Free price input'),
),
migrations.AlterField(
model_name='question',
name='type',
field=models.CharField(choices=[('N', 'Number'), ('S', 'Text (one line)'), ('T', 'Multiline text'), ('B', 'Yes/No'), ('C', 'Choose one from a list'), ('M', 'Choose multiple from a list')], max_length=5, verbose_name='Question type'),
),
migrations.AddField(
model_name='questionoption',
name='question',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='pretixbase.Question'),
),
migrations.AddField(
model_name='questionanswer',
name='option',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='answers', to='pretixbase.QuestionOption'),
),
]

View File

@@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.2 on 2016-03-26 11:39
from __future__ import unicode_literals
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0018_auto_20160326_1104'),
]
operations = [
migrations.RemoveField(
model_name='questionanswer',
name='option',
),
migrations.AddField(
model_name='questionanswer',
name='options',
field=models.ManyToManyField(blank=True, null=True, related_name='answers', to='pretixbase.QuestionOption'),
),
migrations.AlterField(
model_name='questionoption',
name='question',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='options', to='pretixbase.Question'),
),
]

View File

@@ -3,7 +3,8 @@ from .base import CachedFile, cachedfile_name
from .event import Event, EventLock, EventPermission, EventSetting
from .invoices import Invoice, InvoiceLine, invoice_filename
from .items import (
Item, ItemCategory, ItemVariation, Question, Quota, itempicture_upload_to,
Item, ItemCategory, ItemVariation, Question, QuestionOption, Quota,
itempicture_upload_to,
)
from .log import LogEntry
from .orders import (
@@ -19,5 +20,5 @@ __all__ = [
'BaseRestriction', 'Quota', 'Order', 'CachedTicket', 'QuestionAnswer', 'AbstractPosition', 'OrderPosition',
'CartPosition', 'EventSetting', 'OrganizerSetting', 'EventLock', 'cachedfile_name', 'itempicture_upload_to',
'generate_secret', 'Voucher', 'LogEntry', 'InvoiceAddress', 'generate_position_secret', 'InvoiceLine',
'Invoice', 'invoice_filename'
'Invoice', 'invoice_filename', 'QuestionOption'
]

View File

@@ -302,6 +302,7 @@ class Question(LoggedModel):
* a one-line string (``TYPE_STRING``)
* a multi-line string (``TYPE_TEXT``)
* a boolean (``TYPE_BOOLEAN``)
* a multiple choice option (``TYPE_CHOICE`` and ``TYPE_CHOICE_MULTIPLE``)
:param event: The event this question belongs to
:type event: Event
@@ -317,11 +318,15 @@ class Question(LoggedModel):
TYPE_STRING = "S"
TYPE_TEXT = "T"
TYPE_BOOLEAN = "B"
TYPE_CHOICE = "C"
TYPE_CHOICE_MULTIPLE = "M"
TYPE_CHOICES = (
(TYPE_NUMBER, _("Number")),
(TYPE_STRING, _("Text (one line)")),
(TYPE_TEXT, _("Multiline text")),
(TYPE_BOOLEAN, _("Yes/No")),
(TYPE_CHOICE, _("Choose one from a list")),
(TYPE_CHOICE_MULTIPLE, _("Choose multiple from a list"))
)
event = models.ForeignKey(
@@ -366,6 +371,14 @@ class Question(LoggedModel):
self.event.get_cache().clear()
class QuestionOption(models.Model):
question = models.ForeignKey('Question', related_name='options')
answer = I18nCharField(verbose_name=_('Answer'))
def __str__(self):
return str(self.answer)
class Quota(LoggedModel):
"""
A quota is a "pool of tickets". It is there to limit the number of items

View File

@@ -12,7 +12,7 @@ from typing import List, Union
from ..decimal import round_decimal
from .base import CachedFile, LoggedModel
from .event import Event
from .items import Item, ItemVariation, Question, Quota
from .items import Item, ItemVariation, Question, QuestionOption, Quota
def generate_secret():
@@ -286,6 +286,9 @@ class QuestionAnswer(models.Model):
question = models.ForeignKey(
Question, related_name='answers'
)
options = models.ManyToManyField(
QuestionOption, related_name='answers', blank=True
)
answer = models.TextField()
def __str__(self):