+
Filter Relationships
- {% load bootstrap4 %}
- {% bootstrap_form form exclude='date' %}
-
-
- {% bootstrap_field form.date %}
-
+ {% bootstrap_form relationship_form exclude='date' %}
-
+
Filter People
+ {% bootstrap_form person_form exclude='date' %}
+
+
Filter Organisations
+ {% bootstrap_form organisation_form exclude='date' %}
+
+
+
+
+
+
+ {% bootstrap_field relationship_form.date %}
+
+
+
+
+ {% bootstrap_field person_form.date %}
+
+
+
+
+ {% bootstrap_field organisation_form.date %}
+
{% buttons %}
diff --git a/people/views/network.py b/people/views/network.py
index 2cd0aec..7f2037d 100644
--- a/people/views/network.py
+++ b/people/views/network.py
@@ -8,32 +8,89 @@ from django.contrib.auth.mixins import LoginRequiredMixin
from django.db.models import Q
from django.forms import ValidationError
from django.utils import timezone
-from django.views.generic import FormView
+from django.views.generic import TemplateView
from people import forms, models, serializers
logger = logging.getLogger(__name__) # pylint: disable=invalid-name
-class NetworkView(LoginRequiredMixin, FormView):
- """
- View to display relationship network.
- """
+def filter_relationships(form, at_date):
+ relationship_answerset_set = models.RelationshipAnswerSet.objects.filter(
+ Q(replaced_timestamp__gte=at_date)
+ | Q(replaced_timestamp__isnull=True),
+ timestamp__lte=at_date)
+
+ # Filter answers to relationship questions
+ for field, values in form.cleaned_data.items():
+ if field.startswith(f'{form.question_prefix}question_') and values:
+ relationship_answerset_set = relationship_answerset_set.filter(
+ question_answers__in=values)
+
+ return models.Relationship.objects.filter(
+ pk__in=relationship_answerset_set.values_list('relationship',
+ flat=True))
+
+
+def filter_people(form, at_date):
+ answerset_set = models.PersonAnswerSet.objects.filter(
+ Q(replaced_timestamp__gte=at_date)
+ | Q(replaced_timestamp__isnull=True),
+ timestamp__lte=at_date)
+
+ # Filter answers to questions
+ for field, values in form.cleaned_data.items():
+ if field.startswith(f'{form.question_prefix}question_') and values:
+ answerset_set = answerset_set.filter(question_answers__in=values)
+
+ return models.Person.objects.filter(
+ pk__in=answerset_set.values_list('person', flat=True))
+
+
+def filter_organisations(form, at_date):
+ answerset_set = models.OrganisationAnswerSet.objects.filter(
+ Q(replaced_timestamp__gte=at_date)
+ | Q(replaced_timestamp__isnull=True),
+ timestamp__lte=at_date)
+
+ # Filter answers to questions
+ for field, values in form.cleaned_data.items():
+ if field.startswith(f'{form.question_prefix}question_') and values:
+ answerset_set = answerset_set.filter(question_answers__in=values)
+
+ return models.Organisation.objects.filter(
+ pk__in=answerset_set.values_list('organisation', flat=True))
+
+
+class NetworkView(LoginRequiredMixin, TemplateView):
+ """View to display relationship network."""
template_name = 'people/network.html'
- form_class = forms.NetworkRelationshipFilterForm
+
+ def post(self, request, *args, **kwargs):
+ forms = self.get_forms()
+ if all(map(lambda f: f.is_valid(), forms.values())):
+ return self.forms_valid(forms)
+
+ return self.forms_invalid(forms)
+
+ def get_forms(self):
+ form_kwargs = self.get_form_kwargs()
+
+ return {
+ 'relationship': forms.NetworkRelationshipFilterForm(**form_kwargs),
+ 'person': forms.NetworkPersonFilterForm(**form_kwargs),
+ 'organisation': forms.NetworkOrganisationFilterForm(**form_kwargs),
+ }
def get_form_kwargs(self):
- """
- Add GET params to form data.
- """
- kwargs = super().get_form_kwargs()
+ """Add GET params to form data."""
+ kwargs = {}
if self.request.method == 'GET':
- if 'data' in kwargs:
- kwargs['data'].update(self.request.GET)
+ kwargs['data'] = self.request.GET
- else:
- kwargs['data'] = self.request.GET
+ if self.request.method in ('POST', 'PUT'):
+ kwargs['data'] = self.request.POST
return kwargs
@@ -42,46 +99,42 @@ class NetworkView(LoginRequiredMixin, FormView):
Add filtered QuerySets of :class:`Person` and :class:`Relationship` to the context.
"""
context = super().get_context_data(**kwargs)
- form: forms.NetworkRelationshipFilterForm = context['form']
- if not form.is_valid():
+
+ forms = self.get_forms()
+ context['relationship_form'] = forms['relationship']
+ context['person_form'] = forms['person']
+ context['organisation_form'] = forms['organisation']
+
+ if not all(map(lambda f: f.is_valid(), forms.values())):
return context
- at_date = form.cleaned_data['date']
- if not at_date:
- at_date = timezone.now().date()
+ relationship_at_date = forms['relationship'].cleaned_data['date']
+ if not relationship_at_date:
+ relationship_at_date = timezone.now().date()
+
+ person_at_date = forms['person'].cleaned_data['date']
+ if not person_at_date:
+ person_at_date = timezone.now().date()
+
+ organisation_at_date = forms['organisation'].cleaned_data['date']
+ if not organisation_at_date:
+ organisation_at_date = timezone.now().date()
# Filter on timestamp__date doesn't seem to work on MySQL
# To compare datetimes we need at_date to be midnight at
# the *end* of the day in question - so add one day here
- at_date += timezone.timedelta(days=1)
-
- relationship_answerset_set = models.RelationshipAnswerSet.objects.filter(
- Q(replaced_timestamp__gte=at_date)
- | Q(replaced_timestamp__isnull=True),
- timestamp__lte=at_date)
-
- logger.info('Found %d relationship answer sets for %s',
- relationship_answerset_set.count(), at_date)
-
- # Filter answers to relationship questions
- for field, values in form.cleaned_data.items():
- if field.startswith(f'{form.question_prefix}question_') and values:
- relationship_answerset_set = relationship_answerset_set.filter(
- question_answers__in=values)
-
- logger.info('Found %d relationship answer sets matching filters',
- relationship_answerset_set.count())
+ relationship_at_date += timezone.timedelta(days=1)
context['person_set'] = serializers.PersonSerializer(
- models.Person.objects.all(), many=True).data
+ filter_people(forms['person'], person_at_date),
+ many=True).data
context['organisation_set'] = serializers.OrganisationSerializer(
- models.Organisation.objects.all(), many=True).data
+ filter_organisations(forms['organisation'], organisation_at_date),
+ many=True).data
context['relationship_set'] = serializers.RelationshipSerializer(
- models.Relationship.objects.filter(
- pk__in=relationship_answerset_set.values_list('relationship',
- flat=True)),
+ filter_relationships(forms['relationship'], relationship_at_date),
many=True).data
logger.info('Found %d distinct relationships matching filters',
@@ -89,9 +142,12 @@ class NetworkView(LoginRequiredMixin, FormView):
return context
- def form_valid(self, form):
+ def forms_valid(self, forms):
try:
return self.render_to_response(self.get_context_data())
except ValidationError:
- return self.form_invalid(form)
+ return self.forms_invalid(forms)
+
+ def forms_invalid(self, forms):
+ return self.render_to_response(self.get_context_data())