feat: add organisation questions to update view

This commit is contained in:
James Graham
2021-02-24 14:59:43 +00:00
parent adf12442a4
commit c8a68d542a
4 changed files with 89 additions and 10 deletions

View File

@@ -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'):

View File

@@ -29,6 +29,10 @@
<hr>
{% include 'people/person/includes/answer_set_full.html' %}
<hr>
<div id="map" style="height: 800px; width: 100%"></div>
<hr>

View File

@@ -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>

View File

@@ -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