mirror of
https://github.com/Southampton-RSG/breccia-mapper.git
synced 2026-03-03 03:17:07 +00:00
Upgrade versions of most packages and make other required changes to ensure compatibility. Update database models and migrations to match new requirements set by Django
167 lines
5.3 KiB
Python
Executable File
167 lines
5.3 KiB
Python
Executable File
import logging
|
|
|
|
from django.db import models
|
|
from django.urls import reverse
|
|
|
|
from django_countries.fields import CountryField
|
|
|
|
from .question import AnswerSet, Question, QuestionChoice
|
|
|
|
logger = logging.getLogger(__name__) # pylint: disable=invalid-name
|
|
|
|
__all__ = [
|
|
'OrganisationQuestion',
|
|
'OrganisationQuestionChoice',
|
|
'Organisation',
|
|
'OrganisationAnswerSet',
|
|
]
|
|
|
|
|
|
class OrganisationQuestion(Question):
|
|
"""Question which may be asked about a Organisation."""
|
|
#: Should answers to this question be displayed on public profiles?
|
|
answer_is_public = models.BooleanField(
|
|
help_text='Should answers to this question be displayed on profiles?',
|
|
default=True,
|
|
blank=False,
|
|
null=False)
|
|
|
|
|
|
class OrganisationQuestionChoice(QuestionChoice):
|
|
"""Allowed answer to a :class:`OrganisationQuestion`."""
|
|
#: Question to which this answer belongs
|
|
question = models.ForeignKey(OrganisationQuestion,
|
|
related_name='answers',
|
|
on_delete=models.CASCADE,
|
|
blank=False,
|
|
null=False)
|
|
class Meta(QuestionChoice.Meta):
|
|
constraints = [
|
|
models.UniqueConstraint(fields=['question', 'text'],
|
|
name='unique_question_answer_organisationquestionchoice')
|
|
]
|
|
|
|
|
|
class Organisation(models.Model):
|
|
"""Organisation to which a :class:`Person` belongs."""
|
|
class Meta:
|
|
ordering = ['name']
|
|
|
|
name = models.CharField(max_length=255, blank=False, null=False)
|
|
|
|
def __str__(self) -> str:
|
|
# Prefer name as in latest OrganisationAnswerSet
|
|
try:
|
|
name = self.current_answers.name
|
|
|
|
except AttributeError:
|
|
name = ''
|
|
|
|
return name or self.name
|
|
|
|
@property
|
|
def current_answers(self) -> 'OrganisationAnswerSet':
|
|
return self.answer_sets.last()
|
|
|
|
def get_absolute_url(self):
|
|
return reverse('people:organisation.detail', kwargs={'pk': self.pk})
|
|
|
|
|
|
class OrganisationAnswerSet(AnswerSet):
|
|
"""The answers to the organisation questions at a particular point in time."""
|
|
|
|
question_model = OrganisationQuestion
|
|
|
|
#: Organisation to which this answer set belongs
|
|
organisation = models.ForeignKey(Organisation,
|
|
on_delete=models.CASCADE,
|
|
related_name='answer_sets',
|
|
blank=False,
|
|
null=False)
|
|
|
|
name = models.CharField(max_length=255, blank=True, null=False)
|
|
|
|
website = models.URLField(max_length=255, blank=True, null=False)
|
|
|
|
#: Which countries does this organisation operate in?
|
|
countries = CountryField(
|
|
multiple=True,
|
|
blank=True,
|
|
null=False,
|
|
help_text=(
|
|
'Geographical spread - in which countries does this organisation '
|
|
'have offices? Select all that apply'))
|
|
|
|
#: Which country is this organisation based in?
|
|
hq_country = CountryField(
|
|
blank=True,
|
|
null=False,
|
|
help_text=(
|
|
'In which country does this organisation have its main location?'))
|
|
|
|
is_partner_organisation = models.BooleanField(default=False,
|
|
blank=False,
|
|
null=False)
|
|
|
|
latitude = models.FloatField(blank=True, null=True)
|
|
|
|
longitude = models.FloatField(blank=True, null=True)
|
|
|
|
#: Answers to :class:`OrganisationQuestion`s
|
|
question_answers = models.ManyToManyField(OrganisationQuestionChoice)
|
|
|
|
@property
|
|
def location_set(self) -> bool:
|
|
return self.latitude and self.longitude
|
|
|
|
def public_answers(self) -> models.QuerySet:
|
|
"""Get answers to questions which are public."""
|
|
return self.question_answers.filter(question__answer_is_public=True)
|
|
|
|
def as_dict(self):
|
|
"""Get the answers from this set as a dictionary for use in Form.initial."""
|
|
exclude_fields = {
|
|
'id',
|
|
'timestamp',
|
|
'replaced_timestamp',
|
|
'organisation_id',
|
|
'question_answers',
|
|
}
|
|
|
|
def field_value_repr(field):
|
|
"""Get the representation of a field's value as required by Form.initial."""
|
|
attr_val = getattr(self, field.attname)
|
|
|
|
# Relation fields need to return PKs
|
|
if isinstance(field, models.ManyToManyField):
|
|
return [obj.pk for obj in attr_val.all()]
|
|
|
|
# But foreign key fields are a PK already so no extra work
|
|
|
|
return attr_val
|
|
|
|
answers = {
|
|
# Foreign key fields have _id at end in model _meta but don't in forms
|
|
field.attname.rstrip('_id'): field_value_repr(field)
|
|
for field in self._meta.get_fields()
|
|
if field.attname not in exclude_fields
|
|
}
|
|
|
|
for answer in self.question_answers.all():
|
|
question = answer.question
|
|
field_name = f'question_{question.pk}'
|
|
|
|
if question.is_multiple_choice:
|
|
if field_name not in answers:
|
|
answers[field_name] = []
|
|
|
|
answers[field_name].append(answer.pk)
|
|
|
|
else:
|
|
answers[field_name] = answer.pk
|
|
|
|
return answers
|
|
|
|
def get_absolute_url(self):
|
|
return self.organisation.get_absolute_url()
|