diff --git a/src/pretix/base/exporters/orderlist.py b/src/pretix/base/exporters/orderlist.py index 02350e63c3..47d90455fd 100644 --- a/src/pretix/base/exporters/orderlist.py +++ b/src/pretix/base/exporters/orderlist.py @@ -32,7 +32,7 @@ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations under the License. -from collections import OrderedDict +from collections import OrderedDict, defaultdict from decimal import Decimal from zoneinfo import ZoneInfo @@ -605,10 +605,9 @@ class OrderListExporter(MultiSheetListExporter): ] questions = list(Question.objects.filter(event__in=self.events)) - options = {} + options = defaultdict(list) for q in questions: if q.type == Question.TYPE_CHOICE_MULTIPLE: - options[q.pk] = [] if form_data['group_multiple_choice']: for o in q.options.all(): options[q.pk].append(o) @@ -618,6 +617,9 @@ class OrderListExporter(MultiSheetListExporter): headers.append(str(q.question) + ' – ' + str(o.answer)) options[q.pk].append(o) else: + if q.type == Question.TYPE_CHOICE: + for o in q.options.all(): + options[q.pk].append(o) headers.append(str(q.question)) headers += [ _('Company'), @@ -727,7 +729,7 @@ class OrderListExporter(MultiSheetListExporter): for a in op.answers.all(): # We do not want to localize Date, Time and Datetime question answers, as those can lead # to difficulties parsing the data (for example 2019-02-01 may become Février, 2019 01 in French). - if a.question.type == Question.TYPE_CHOICE_MULTIPLE: + if a.question.type in (Question.TYPE_CHOICE_MULTIPLE, Question.TYPE_CHOICE): acache[a.question_id] = set(o.pk for o in a.options.all()) elif a.question.type in Question.UNLOCALIZED_TYPES: acache[a.question_id] = a.answer @@ -740,6 +742,10 @@ class OrderListExporter(MultiSheetListExporter): else: for o in options[q.pk]: row.append(_('Yes') if o.pk in acache.get(q.pk, set()) else _('No')) + elif q.type == Question.TYPE_CHOICE: + # Join is only necessary if the question type was modified but also keeps the code simpler here + # as we'd otherwise need some [0] and existance checks + row.append(", ".join(str(o.answer) for o in options[q.pk] if o.pk in acache.get(q.pk, set()))) else: row.append(acache.get(q.pk, '')) diff --git a/src/pretix/plugins/checkinlists/exporters.py b/src/pretix/plugins/checkinlists/exporters.py index 85b3d695f1..27ca56a202 100644 --- a/src/pretix/plugins/checkinlists/exporters.py +++ b/src/pretix/plugins/checkinlists/exporters.py @@ -281,6 +281,17 @@ class TableTextRotate(Flowable): canvas.drawString(0, -1, self.text) +def format_answer_for_export(a): + if a.question.type in (Question.TYPE_CHOICE, Question.TYPE_CHOICE_MULTIPLE): + return ", ".join(str(o.answer) for o in a.options.all()) + elif a.question.type in Question.UNLOCALIZED_TYPES: + # We do not want to localize Date, Time and Datetime question answers, as those can lead + # to difficulties parsing the data (for example 2019-02-01 may become Février, 2019 01 in French). + return a.answer + else: + return str(a) + + class PDFCheckinList(ReportlabExportMixin, CheckInListMixin, BaseExporter): name = "overview" identifier = 'checkinlistpdf' @@ -372,6 +383,14 @@ class PDFCheckinList(ReportlabExportMixin, CheckInListMixin, BaseExporter): tdata[0].append(p) qs = self._get_queryset(cl, form_data) + qs = qs.prefetch_related( + 'answers', + 'answers__options', + 'answers__question', + 'addon_to__answers', + 'addon_to__answers__question', + 'addon_to__answers__options', + ) for op in qs: try: @@ -413,19 +432,9 @@ class PDFCheckinList(ReportlabExportMixin, CheckInListMixin, BaseExporter): acache = {} if op.addon_to: for a in op.addon_to.answers.all(): - # We do not want to localize Date, Time and Datetime question answers, as those can lead - # to difficulties parsing the data (for example 2019-02-01 may become Février, 2019 01 in French). - if a.question.type in Question.UNLOCALIZED_TYPES: - acache[a.question_id] = a.answer - else: - acache[a.question_id] = str(a) + acache[a.question_id] = format_answer_for_export(a) for a in op.answers.all(): - # We do not want to localize Date, Time and Datetime question answers, as those can lead - # to difficulties parsing the data (for example 2019-02-01 may become Février, 2019 01 in French). - if a.question.type in Question.UNLOCALIZED_TYPES: - acache[a.question_id] = a.answer - else: - acache[a.question_id] = str(a) + acache[a.question_id] = format_answer_for_export(a) for q in questions: txt = acache.get(q.pk, '') txt = bleach.clean(txt, tags=['br']).strip().replace('
', '
') @@ -525,7 +534,12 @@ class CSVCheckinList(CheckInListMixin, ListExporter): yield headers qs = base_qs.prefetch_related( - 'answers', 'answers__question', 'addon_to__answers', 'addon_to__answers__question' + 'answers', + 'answers__options', + 'answers__question', + 'addon_to__answers', + 'addon_to__answers__question', + 'addon_to__answers__options', ) all_ids = list(base_qs.values_list('pk', flat=True)) @@ -597,19 +611,9 @@ class CSVCheckinList(CheckInListMixin, ListExporter): acache = {} if op.addon_to: for a in op.addon_to.answers.all(): - # We do not want to localize Date, Time and Datetime question answers, as those can lead - # to difficulties parsing the data (for example 2019-02-01 may become Février, 2019 01 in French). - if a.question.type in Question.UNLOCALIZED_TYPES: - acache[a.question_id] = a.answer - else: - acache[a.question_id] = str(a) + acache[a.question_id] = format_answer_for_export(a) for a in op.answers.all(): - # We do not want to localize Date, Time and Datetime question answers, as those can lead - # to difficulties parsing the data (for example 2019-02-01 may become Février, 2019 01 in French). - if a.question.type in Question.UNLOCALIZED_TYPES: - acache[a.question_id] = a.answer - else: - acache[a.question_id] = str(a) + acache[a.question_id] = format_answer_for_export(a) for q in questions: row.append(acache.get(q.pk, ''))