From 76270c45722059483385aeb0346fe8660402ab66 Mon Sep 17 00:00:00 2001 From: James Graham Date: Wed, 1 Apr 2020 13:15:48 +0100 Subject: [PATCH] feat: Export relationships with answers See #27 See #29 Resolves #25 --- people/models/relationship.py | 9 +++++++++ people/serializers.py | 33 +++++++++++++++++++++++---------- people/views/export.py | 5 +++-- 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/people/models/relationship.py b/people/models/relationship.py index 9065ac8..c141810 100644 --- a/people/models/relationship.py +++ b/people/models/relationship.py @@ -6,6 +6,7 @@ import typing from django.db import models from django.urls import reverse +from django.utils.text import slugify from .person import Person @@ -47,6 +48,10 @@ class RelationshipQuestion(models.Model): return [ [choice.pk, str(choice)] for choice in self.answers.all() ] + + @property + def slug(self) -> str: + return slugify(self.text) def __str__(self) -> str: return self.text @@ -80,6 +85,10 @@ class RelationshipQuestionChoice(models.Model): order = models.SmallIntegerField(default=0, blank=False, null=False) + @property + def slug(self) -> str: + return slugify(self.text) + def __str__(self) -> str: return self.text diff --git a/people/serializers.py b/people/serializers.py index 3763756..8d820f7 100644 --- a/people/serializers.py +++ b/people/serializers.py @@ -46,13 +46,15 @@ class FlattenedModelSerializer(serializers.ModelSerializer): return data_out @property - def column_headers(self) -> typing.Collection: + def column_headers(self) -> typing.List[str]: """ Get all column headers that will be output by this serializer. """ - return self.flatten_data(self.fields, - sub_type=serializers.BaseSerializer, - sub_value_accessor=lambda x: x.fields.items()) + fields = self.flatten_data(self.fields, + sub_type=serializers.BaseSerializer, + sub_value_accessor=lambda x: x.fields.items()) + + return list(fields) def to_representation(self, instance) -> typing.OrderedDict: """ @@ -99,15 +101,26 @@ class RelationshipSerializer(FlattenedModelSerializer): 'source', 'target', ] + + @property + def column_headers(self) -> typing.List[str]: + headers = super().column_headers + + # Add relationship questions to columns + for question in models.RelationshipQuestion.objects.all(): + headers.append(question.slug) + + return headers def to_representation(self, instance): rep = super().to_representation(instance) - # try: - # for answer in instance.current_answers.question_answers.all(): - # rep[answer.question.text] = answer.text - # - # except AttributeError: - # pass + try: + # Add relationship question answers to data + for answer in instance.current_answers.question_answers.all(): + rep[answer.question.slug] = answer.slug + + except AttributeError: + pass return rep diff --git a/people/views/export.py b/people/views/export.py index c4bdc88..e57ba2b 100644 --- a/people/views/export.py +++ b/people/views/export.py @@ -15,8 +15,9 @@ class CsvExportView(LoginRequiredMixin, BaseListView): def render_to_response(self, context: typing.Dict) -> HttpResponse: response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = f'attachment; filename="{self.get_context_object_name(self.object_list)}.csv"' - - serializer = self.serializer_class(self.get_queryset(), many=True) + + # Force ordering by PK - though this should be default anyway + serializer = self.serializer_class(self.get_queryset().order_by('pk'), many=True) writer = csv.DictWriter(response, fieldnames=serializer.child.column_headers) writer.writeheader()