mirror of
https://github.com/Southampton-RSG/breccia-mapper.git
synced 2026-03-03 03:17:07 +00:00
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,10 +22,10 @@ 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)
|
||||
|
||||
|
||||
return response
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user