fix: update exports for static answerset fields

Resolves #99
This commit is contained in:
James Graham
2021-05-17 18:26:52 +01:00
parent 479ef038d4
commit f37d7c77c4
5 changed files with 57 additions and 68 deletions

View File

@@ -104,7 +104,6 @@ The most likely required settings are: SECRET_KEY, DEBUG, ALLOWED_HOSTS, DATABAS
Google Maps API key to display maps of people's locations
"""
import collections
import logging
import logging.config
import pathlib

View File

@@ -5,6 +5,38 @@ from people import models
from . import base
def underscore(slug: str) -> str:
"""Replace hyphens with underscores in text."""
return slug.replace('-', '_')
def underscore_dict_keys(dict_: typing.Mapping[str, typing.Any]):
return {underscore(key): value for key, value in dict_.items()}
class AnswerSetSerializer(base.FlattenedModelSerializer):
question_model = None
@property
def column_headers(self) -> typing.List[str]:
headers = super().column_headers
# Add relationship questions to columns
for question in self.question_model.objects.all():
headers.append(underscore(question.slug))
return headers
def to_representation(self, instance: models.question.AnswerSet):
rep = super().to_representation(instance)
rep.update(
underscore_dict_keys(instance.build_question_answers(use_slugs=True, show_all=True))
)
return rep
class PersonSerializer(base.FlattenedModelSerializer):
class Meta:
model = models.Person
@@ -14,7 +46,8 @@ class PersonSerializer(base.FlattenedModelSerializer):
]
class PersonAnswerSetSerializer(base.FlattenedModelSerializer):
class PersonAnswerSetSerializer(AnswerSetSerializer):
question_model = models.PersonQuestion
person = PersonSerializer()
class Meta:
@@ -24,38 +57,10 @@ class PersonAnswerSetSerializer(base.FlattenedModelSerializer):
'person',
'timestamp',
'replaced_timestamp',
'nationality',
'country_of_residence',
'organisation',
'organisation_started_date',
'job_title',
'latitude',
'longitude',
]
@property
def column_headers(self) -> typing.List[str]:
headers = super().column_headers
# Add questions to columns
for question in models.PersonQuestion.objects.all():
headers.append(underscore(question.slug))
return headers
def to_representation(self, instance):
rep = super().to_representation(instance)
try:
# Add relationship question answers to data
for answer in instance.question_answers.all():
rep[underscore(answer.question.slug)] = underscore(answer.slug)
except AttributeError:
pass
return rep
class RelationshipSerializer(base.FlattenedModelSerializer):
source = PersonSerializer()
@@ -70,12 +75,8 @@ class RelationshipSerializer(base.FlattenedModelSerializer):
]
def underscore(slug: str) -> str:
"""Replace hyphens with underscores in text."""
return slug.replace('-', '_')
class RelationshipAnswerSetSerializer(base.FlattenedModelSerializer):
class RelationshipAnswerSetSerializer(AnswerSetSerializer):
question_model = models.RelationshipQuestion
relationship = RelationshipSerializer()
class Meta:
@@ -86,26 +87,3 @@ class RelationshipAnswerSetSerializer(base.FlattenedModelSerializer):
'timestamp',
'replaced_timestamp',
]
@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(underscore(question.slug))
return headers
def to_representation(self, instance):
rep = super().to_representation(instance)
try:
# Add relationship question answers to data
for answer in instance.question_answers.all():
rep[underscore(answer.question.slug)] = underscore(answer.slug)
except AttributeError:
pass
return rep

View File

@@ -7,6 +7,10 @@ from django.views.generic import TemplateView
from django.views.generic.list import BaseListView
class QuotedCsv(csv.excel):
quoting = csv.QUOTE_NONNUMERIC
class CsvExportView(LoginRequiredMixin, BaseListView):
model = None
serializer_class = None
@@ -18,7 +22,7 @@ class CsvExportView(LoginRequiredMixin, BaseListView):
# 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 = csv.DictWriter(response, dialect=QuotedCsv, fieldnames=serializer.child.column_headers)
writer.writeheader()
writer.writerows(serializer.data)

View File

@@ -8,6 +8,7 @@ class PersonExportView(base.CsvExportView):
model = models.person.Person
serializer_class = serializers.people.PersonSerializer
class PersonAnswerSetExportView(base.CsvExportView):
model = models.person.PersonAnswerSet
serializer_class = serializers.people.PersonAnswerSetSerializer

View File

@@ -166,27 +166,34 @@ class AnswerSet(models.Model):
def is_current(self) -> bool:
return self.replaced_timestamp is None
def build_question_answers(self, show_all: bool = False) -> typing.Dict[str, str]:
def build_question_answers(self,
show_all: bool = False,
use_slugs: bool = False) -> typing.Dict[str, str]:
"""Collect answers to dynamic questions and join with commas."""
questions = self.question_model.objects.all()
if not show_all:
questions = questions.filter(answer_is_public=True)
question_answers = {}
try:
answerset_answers = list(self.question_answers.order_by().values('text', 'question_id'))
for question in questions:
key = question.slug if use_slugs else question.text
if question.hardcoded_field:
answer = getattr(self, question.hardcoded_field)
if isinstance(answer, list):
answer = ', '.join(map(str, answer))
question_answers[question.text] = answer
else:
answers = self.question_answers.filter(
question=question)
question_answers[question.text] = ', '.join(
map(str, answers))
answer = ', '.join(
answer['text'] for answer in answerset_answers
if answer['question_id'] == question.id
)
question_answers[key] = answer
except AttributeError:
# No AnswerSet yet