mirror of
https://github.com/Southampton-RSG/breccia-mapper.git
synced 2026-03-03 03:17:07 +00:00
feat: add organisation questions to update view
This commit is contained in:
@@ -57,7 +57,7 @@ class DynamicAnswerSetBase(forms.Form):
|
||||
field = field_class(label=question,
|
||||
queryset=question.answers,
|
||||
widget=field_widget,
|
||||
required=self.field_required,
|
||||
required=self.field_required and not question.allow_free_text,
|
||||
initial=initial.get(field_name, None))
|
||||
self.fields[field_name] = field
|
||||
|
||||
@@ -67,6 +67,48 @@ class DynamicAnswerSetBase(forms.Form):
|
||||
self.fields[f'{field_name}_free'] = free_field
|
||||
|
||||
|
||||
class OrganisationAnswerSetForm(forms.ModelForm, DynamicAnswerSetBase):
|
||||
"""Form for variable organisation attributes.
|
||||
|
||||
Dynamic fields inspired by https://jacobian.org/2010/feb/28/dynamic-form-generation/
|
||||
"""
|
||||
class Meta:
|
||||
model = models.OrganisationAnswerSet
|
||||
fields = []
|
||||
|
||||
question_model = models.OrganisationQuestion
|
||||
answer_model = models.OrganisationQuestionChoice
|
||||
|
||||
def save(self, commit=True) -> models.OrganisationAnswerSet:
|
||||
# Save model
|
||||
self.instance = super().save(commit=False)
|
||||
self.instance.organisation_id = self.initial['organisation_id']
|
||||
if commit:
|
||||
self.instance.save()
|
||||
# Need to call same_m2m manually since we use commit=False above
|
||||
self.save_m2m()
|
||||
|
||||
if commit:
|
||||
# Save answers to questions
|
||||
for key, value in self.cleaned_data.items():
|
||||
if key.startswith('question_') and value:
|
||||
if key.endswith('_free'):
|
||||
# Create new answer from free text
|
||||
value, _ = self.answer_model.objects.get_or_create(
|
||||
text=value,
|
||||
question=self.question_model.objects.get(
|
||||
pk=key.split('_')[1]))
|
||||
|
||||
try:
|
||||
self.instance.question_answers.add(value)
|
||||
|
||||
except TypeError:
|
||||
# Value is a QuerySet - multiple choice question
|
||||
self.instance.question_answers.add(*value.all())
|
||||
|
||||
return self.instance
|
||||
|
||||
|
||||
class PersonAnswerSetForm(forms.ModelForm, DynamicAnswerSetBase):
|
||||
"""Form for variable person attributes.
|
||||
|
||||
@@ -101,7 +143,7 @@ class PersonAnswerSetForm(forms.ModelForm, DynamicAnswerSetBase):
|
||||
answer_model = models.PersonQuestionChoice
|
||||
|
||||
def save(self, commit=True) -> models.PersonAnswerSet:
|
||||
# Save Relationship model
|
||||
# Save model
|
||||
self.instance = super().save(commit=False)
|
||||
self.instance.person_id = self.initial['person_id']
|
||||
if commit:
|
||||
@@ -110,7 +152,7 @@ class PersonAnswerSetForm(forms.ModelForm, DynamicAnswerSetBase):
|
||||
self.save_m2m()
|
||||
|
||||
if commit:
|
||||
# Save answers to relationship questions
|
||||
# Save answers to questions
|
||||
for key, value in self.cleaned_data.items():
|
||||
if key.startswith('question_') and value:
|
||||
if key.endswith('_free'):
|
||||
@@ -146,11 +188,11 @@ class RelationshipAnswerSetForm(forms.ModelForm, DynamicAnswerSetBase):
|
||||
answer_model = models.RelationshipQuestionChoice
|
||||
|
||||
def save(self, commit=True) -> models.RelationshipAnswerSet:
|
||||
# Save Relationship model
|
||||
# Save model
|
||||
self.instance = super().save(commit=commit)
|
||||
|
||||
if commit:
|
||||
# Save answers to relationship questions
|
||||
# Save answers to questions
|
||||
for key, value in self.cleaned_data.items():
|
||||
if key.startswith('question_') and value:
|
||||
if key.endswith('_free'):
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
|
||||
<hr>
|
||||
|
||||
{% include 'people/person/includes/answer_set_full.html' %}
|
||||
|
||||
<hr>
|
||||
|
||||
<div id="map" style="height: 800px; width: 100%"></div>
|
||||
|
||||
<hr>
|
||||
|
||||
@@ -33,10 +33,7 @@
|
||||
{% csrf_token %}
|
||||
|
||||
{% load bootstrap4 %}
|
||||
{% bootstrap_form form exclude='latitude,longitude' %}
|
||||
|
||||
{% bootstrap_field form.latitude %}
|
||||
{% bootstrap_field form.longitude %}
|
||||
{% bootstrap_form form %}
|
||||
|
||||
{% buttons %}
|
||||
<button class="btn btn-success" type="submit">Submit</button>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import typing
|
||||
|
||||
from django.contrib.auth.mixins import LoginRequiredMixin
|
||||
from django.utils import timezone
|
||||
from django.views.generic import CreateView, DetailView, ListView, UpdateView
|
||||
|
||||
from people import forms, models
|
||||
@@ -30,6 +31,7 @@ class OrganisationDetailView(LoginRequiredMixin, DetailView):
|
||||
"""Add map marker to context."""
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
context['answer_set'] = self.object.current_answers
|
||||
context['map_markers'] = [{
|
||||
'name': self.object.name,
|
||||
'lat': self.object.latitude,
|
||||
@@ -44,7 +46,7 @@ class OrganisationUpdateView(LoginRequiredMixin, UpdateView):
|
||||
model = models.Organisation
|
||||
context_object_name = 'organisation'
|
||||
template_name = 'people/organisation/update.html'
|
||||
form_class = forms.OrganisationForm
|
||||
form_class = forms.OrganisationAnswerSetForm
|
||||
|
||||
def get_context_data(self,
|
||||
**kwargs: typing.Any) -> typing.Dict[str, typing.Any]:
|
||||
@@ -58,3 +60,37 @@ class OrganisationUpdateView(LoginRequiredMixin, UpdateView):
|
||||
}]
|
||||
|
||||
return context
|
||||
|
||||
def get_initial(self) -> typing.Dict[str, typing.Any]:
|
||||
try:
|
||||
previous_answers = self.object.current_answers.as_dict()
|
||||
|
||||
except AttributeError:
|
||||
previous_answers = {}
|
||||
|
||||
previous_answers.update({
|
||||
'organisation_id': self.object.id,
|
||||
})
|
||||
|
||||
return previous_answers
|
||||
|
||||
def get_form_kwargs(self) -> typing.Dict[str, typing.Any]:
|
||||
"""Remove instance from form kwargs as it's an Organisation, but expects an OrganisationAnswerSet."""
|
||||
kwargs = super().get_form_kwargs()
|
||||
kwargs.pop('instance')
|
||||
|
||||
return kwargs
|
||||
|
||||
def form_valid(self, form):
|
||||
"""Mark any previous answer sets as replaced."""
|
||||
response = super().form_valid(form)
|
||||
now_date = timezone.now().date()
|
||||
|
||||
# Saving the form made self.object an OrganisationAnswerSet - so go up, then back down
|
||||
# Shouldn't be more than one after initial updates after migration
|
||||
for answer_set in self.object.organisation.answer_sets.exclude(
|
||||
pk=self.object.pk):
|
||||
answer_set.replaced_timestamp = now_date
|
||||
answer_set.save()
|
||||
|
||||
return response
|
||||
|
||||
Reference in New Issue
Block a user