refactor: update forms to match moved questions

This commit is contained in:
James Graham
2020-12-02 15:53:30 +00:00
parent 2027d9d3ab
commit 6bb4f09454
2 changed files with 84 additions and 24 deletions

View File

@@ -25,29 +25,12 @@ def get_date_year_range() -> typing.Iterable[int]:
class PersonForm(forms.ModelForm): class PersonForm(forms.ModelForm):
""" """Form for creating / updating an instance of :class:`Person`."""
Form for creating / updating an instance of :class:`Person`.
"""
class Meta: class Meta:
model = models.Person model = models.Person
fields = [ fields = [
'name', 'name',
] ]
widgets = {
'nationality': Select2Widget(),
'country_of_residence': Select2Widget(),
'themes': Select2MultipleWidget(),
}
help_texts = {
'organisation_started_date':
'If you don\'t know the exact date, an approximate date is okay.',
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['organisation_started_date'].widget = SelectDateWidget(
years=get_date_year_range())
class RelationshipForm(forms.Form): class RelationshipForm(forms.Form):
@@ -60,11 +43,12 @@ class DynamicAnswerSetBase(forms.Form):
field_class = forms.ModelChoiceField field_class = forms.ModelChoiceField
field_widget = None field_widget = None
field_required = True field_required = True
question_model = None
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
for question in models.RelationshipQuestion.objects.all(): for question in self.question_model.objects.all():
field = self.field_class(label=question, field = self.field_class(label=question,
queryset=question.answers, queryset=question.answers,
widget=self.field_widget, widget=self.field_widget,
@@ -72,6 +56,47 @@ class DynamicAnswerSetBase(forms.Form):
self.fields['question_{}'.format(question.pk)] = field self.fields['question_{}'.format(question.pk)] = field
class PersonAnswerSetForm(forms.ModelForm, DynamicAnswerSetBase):
"""Form for variable person attributes.
Dynamic fields inspired by https://jacobian.org/2010/feb/28/dynamic-form-generation/
"""
class Meta:
model = models.PersonAnswerSet
fields = [
'nationality',
'country_of_residence',
'organisation',
'organisation_started_date',
'job_title',
'disciplines',
'themes',
]
widgets = {
'nationality': Select2Widget(),
'country_of_residence': Select2Widget(),
'themes': Select2MultipleWidget(),
}
help_texts = {
'organisation_started_date':
'If you don\'t know the exact date, an approximate date is okay.',
}
question_model = models.PersonQuestion
def save(self, commit=True) -> models.PersonAnswerSet:
# Save Relationship model
self.instance = super().save(commit=commit)
if commit:
# Save answers to relationship questions
for key, value in self.cleaned_data.items():
if key.startswith('question_') and value:
self.instance.question_answers.add(value)
return self.instance
class RelationshipAnswerSetForm(forms.ModelForm, DynamicAnswerSetBase): class RelationshipAnswerSetForm(forms.ModelForm, DynamicAnswerSetBase):
""" """
Form to allow users to describe a relationship. Form to allow users to describe a relationship.
@@ -84,6 +109,8 @@ class RelationshipAnswerSetForm(forms.ModelForm, DynamicAnswerSetBase):
'relationship', 'relationship',
] ]
question_model = models.RelationshipQuestion
def save(self, commit=True) -> models.RelationshipAnswerSet: def save(self, commit=True) -> models.RelationshipAnswerSet:
# Save Relationship model # Save Relationship model
self.instance = super().save(commit=commit) self.instance = super().save(commit=commit)
@@ -104,6 +131,7 @@ class NetworkFilterForm(DynamicAnswerSetBase):
field_class = forms.ModelMultipleChoiceField field_class = forms.ModelMultipleChoiceField
field_widget = Select2MultipleWidget field_widget = Select2MultipleWidget
field_required = False field_required = False
question_model = models.RelationshipQuestion
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)

View File

@@ -3,6 +3,7 @@ Views for displaying or manipulating instances of :class:`Person`.
""" """
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.utils import timezone
from django.views.generic import CreateView, DetailView, ListView, UpdateView from django.views.generic import CreateView, DetailView, ListView, UpdateView
from people import forms, models, permissions from people import forms, models, permissions
@@ -55,9 +56,40 @@ class ProfileView(permissions.UserIsLinkedPersonMixin, DetailView):
class PersonUpdateView(permissions.UserIsLinkedPersonMixin, UpdateView): class PersonUpdateView(permissions.UserIsLinkedPersonMixin, UpdateView):
""" """View for updating a :class:`Person` record."""
View for updating a :class:`Person` record. model = models.PersonAnswerSet
"""
model = models.Person
template_name = 'people/person/update.html' template_name = 'people/person/update.html'
form_class = forms.PersonForm form_class = forms.PersonAnswerSetForm
def get_test_person(self) -> models.Person:
"""Get the person instance which should be used for access control checks."""
return models.Person.objects.get(pk=self.kwargs.get('pk'))
def get(self, request, *args, **kwargs):
self.person = models.Person.objects.get(pk=self.kwargs.get('pk'))
return super().get(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
self.person = models.Person.objects.get(pk=self.kwargs.get('pk'))
return super().post(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['person'] = self.person
return context
def form_valid(self, form):
"""Mark any previous answer sets as replaced."""
response = super().form_valid(form)
now_date = timezone.now().date()
# Shouldn't be more than one after initial updates after migration
for answer_set in self.person.answer_sets.exclude(pk=self.object.pk):
answer_set.replaced_timestamp = now_date
answer_set.save()
return response