From 2cdc7675c70afd0e7a4b2721dc465f0344ac55a3 Mon Sep 17 00:00:00 2001 From: James Graham Date: Fri, 27 Mar 2020 15:15:18 +0000 Subject: [PATCH] refactor: Split people.views into multiple modules --- people/urls.py | 22 ++-- people/views/__init__.py | 9 ++ people/views/network.py | 72 ++++++++++ people/views/person.py | 78 +++++++++++ people/{views.py => views/relationship.py} | 146 ++------------------- 5 files changed, 178 insertions(+), 149 deletions(-) create mode 100644 people/views/__init__.py create mode 100644 people/views/network.py create mode 100644 people/views/person.py rename people/{views.py => views/relationship.py} (50%) diff --git a/people/urls.py b/people/urls.py index de38945..d484424 100644 --- a/people/urls.py +++ b/people/urls.py @@ -7,46 +7,46 @@ app_name = 'people' urlpatterns = [ path('profile/', - views.ProfileView.as_view(), + views.person.ProfileView.as_view(), name='person.profile'), path('people/create', - views.PersonCreateView.as_view(), + views.person.PersonCreateView.as_view(), name='person.create'), path('people', - views.PersonListView.as_view(), + views.person.PersonListView.as_view(), name='person.list'), path('people/', - views.ProfileView.as_view(), + views.person.ProfileView.as_view(), name='person.detail'), path('people//update', - views.PersonUpdateView.as_view(), + views.person.PersonUpdateView.as_view(), name='person.update'), path('people//relationships/create', - views.RelationshipCreateView.as_view(), + views.relationship.RelationshipCreateView.as_view(), name='person.relationship.create'), path('relationships/', - views.RelationshipDetailView.as_view(), + views.relationship.RelationshipDetailView.as_view(), name='relationship.detail'), path('relationships//update', - views.RelationshipUpdateView.as_view(), + views.relationship.RelationshipUpdateView.as_view(), name='relationship.update'), path('api/people', - views.PersonApiView.as_view(), + views.person.PersonApiView.as_view(), name='person.api.list'), path('api/relationships', - views.RelationshipApiView.as_view(), + views.relationship.RelationshipApiView.as_view(), name='relationship.api.list'), path('network', - views.NetworkView.as_view(), + views.network.NetworkView.as_view(), name='network'), ] diff --git a/people/views/__init__.py b/people/views/__init__.py new file mode 100644 index 0000000..39dd5c9 --- /dev/null +++ b/people/views/__init__.py @@ -0,0 +1,9 @@ +""" +Views for displaying or manipulating models within the `people` app. +""" + +from . import ( + network, + person, + relationship +) diff --git a/people/views/network.py b/people/views/network.py new file mode 100644 index 0000000..3e02efa --- /dev/null +++ b/people/views/network.py @@ -0,0 +1,72 @@ +""" +Views for displaying networks of :class:`People` and :class:`Relationship`s. +""" + +from django.contrib.auth.mixins import LoginRequiredMixin +from django.db.models import Q +from django.utils import timezone +from django.views.generic import FormView + + +from people import forms, models, serializers + + +class NetworkView(LoginRequiredMixin, FormView): + """ + View to display relationship network. + """ + template_name = 'people/network.html' + form_class = forms.NetworkFilterForm + + def get_form_kwargs(self): + """ + Add GET params to form data. + """ + kwargs = super().get_form_kwargs() + + if self.request.method == 'GET': + if 'data' in kwargs: + kwargs['data'].update(self.request.GET) + + else: + kwargs['data'] = self.request.GET + + return kwargs + + def get_context_data(self, **kwargs): + """ + Add filtered QuerySets of :class:`Person` and :class:`Relationship` to the context. + """ + context = super().get_context_data(**kwargs) + form = context['form'] + + at_time = timezone.now() + + relationship_set = models.Relationship.objects.all() + + # Filter answers to relationship questions + for key, value in form.data.items(): + if key.startswith('question_') and value: + question_id = key.replace('question_', '', 1) + answer = models.RelationshipQuestionChoice.objects.get(pk=value, + question__pk=question_id) + relationship_set = relationship_set.filter( + Q(answer_sets__replaced_timestamp__gt=at_time) | Q(answer_sets__replaced_timestamp__isnull=True), + answer_sets__timestamp__lte=at_time, + answer_sets__question_answers=answer + ) + + context['person_set'] = serializers.PersonSerializer( + models.Person.objects.all(), + many=True + ).data + + context['relationship_set'] = serializers.RelationshipSerializer( + relationship_set, + many=True + ).data + + return context + + def form_valid(self, form): + return self.render_to_response(self.get_context_data()) diff --git a/people/views/person.py b/people/views/person.py new file mode 100644 index 0000000..c868e9d --- /dev/null +++ b/people/views/person.py @@ -0,0 +1,78 @@ +""" +Views for displaying or manipulating instances of :class:`Person`. +""" + +from django.views.generic import CreateView, DetailView, ListView, UpdateView + +from rest_framework.views import APIView, Response + +from people import forms, models, permissions, serializers + + +class PersonCreateView(CreateView): + """ + View to create a new instance of :class:`Person`. + + If 'user' is passed as a URL parameter - link the new person to the current user. + """ + model = models.Person + template_name = 'people/person/create.html' + form_class = forms.PersonForm + + def form_valid(self, form): + if 'user' in self.request.GET: + form.instance.user = self.request.user + + return super().form_valid(form) + + +class PersonListView(ListView): + """ + View displaying a list of :class:`Person` objects - searchable. + """ + model = models.Person + template_name = 'people/person/list.html' + + +class ProfileView(permissions.UserIsLinkedPersonMixin, DetailView): + """ + View displaying the profile of a :class:`Person` - who may be a user. + """ + model = models.Person + template_name = 'people/person/detail.html' + + def get_object(self, queryset=None) -> models.Person: + """ + Get the :class:`Person` object to be represented by this page. + + If not determined from url get current user. + """ + try: + return super().get_object(queryset) + + except AttributeError: + # pk was not provided in URL + return self.request.user.person + + +class PersonUpdateView(permissions.UserIsLinkedPersonMixin, UpdateView): + """ + View for updating a :class:`Person` record. + """ + model = models.Person + template_name = 'people/person/update.html' + form_class = forms.PersonForm + + +class PersonApiView(APIView): + """ + List all :class:`Person` instances. + """ + + def get(self, request, format=None): + """ + List all :class:`Person` instances. + """ + serializer = serializers.PersonSerializer(models.Person.objects.all(), + many=True) + return Response(serializer.data) diff --git a/people/views.py b/people/views/relationship.py similarity index 50% rename from people/views.py rename to people/views/relationship.py index 35c06ea..3e2c7d5 100644 --- a/people/views.py +++ b/people/views/relationship.py @@ -1,71 +1,14 @@ """ -Views for displaying or manipulating models in the 'people' app. +Views for displaying or manipulating instances of :class:`Relationship`. """ -from django.contrib.auth.mixins import LoginRequiredMixin -from django.db.models import Q from django.urls import reverse from django.utils import timezone -from django.views.generic import CreateView, DetailView, FormView, ListView, UpdateView +from django.views.generic import CreateView, DetailView from rest_framework.views import APIView, Response -from . import forms, models, permissions, serializers - - -class PersonCreateView(CreateView): - """ - View to create a new instance of :class:`Person`. - - If 'user' is passed as a URL parameter - link the new person to the current user. - """ - model = models.Person - template_name = 'people/person/create.html' - form_class = forms.PersonForm - - def form_valid(self, form): - if 'user' in self.request.GET: - form.instance.user = self.request.user - - return super().form_valid(form) - - -class PersonListView(ListView): - """ - View displaying a list of :class:`Person` objects - searchable. - """ - model = models.Person - template_name = 'people/person/list.html' - - -class ProfileView(permissions.UserIsLinkedPersonMixin, DetailView): - """ - View displaying the profile of a :class:`Person` - who may be a user. - """ - model = models.Person - template_name = 'people/person/detail.html' - - def get_object(self, queryset=None) -> models.Person: - """ - Get the :class:`Person` object to be represented by this page. - - If not determined from url get current user. - """ - try: - return super().get_object(queryset) - - except AttributeError: - # pk was not provided in URL - return self.request.user.person - - -class PersonUpdateView(permissions.UserIsLinkedPersonMixin, UpdateView): - """ - View for updating a :class:`Person` record. - """ - model = models.Person - template_name = 'people/person/update.html' - form_class = forms.PersonForm +from people import forms, models, permissions, serializers class RelationshipDetailView(permissions.UserIsLinkedPersonMixin, DetailView): @@ -165,12 +108,12 @@ class RelationshipUpdateView(permissions.UserIsLinkedPersonMixin, CreateView): context['relationship'] = self.relationship return context - + def get_initial(self): initial = super().get_initial() - + initial['relationship'] = self.relationship - + return initial def form_valid(self, form): @@ -187,25 +130,13 @@ class RelationshipUpdateView(permissions.UserIsLinkedPersonMixin, CreateView): answer_set.save() return response - -class PersonApiView(APIView): - """ - List all :class:`Person` instances. - """ - def get(self, request, format=None): - """ - List all :class:`Person` instances. - """ - serializer = serializers.PersonSerializer(models.Person.objects.all(), - many=True) - return Response(serializer.data) - - + class RelationshipApiView(APIView): """ List all :class:`Relationship` instances. """ + def get(self, request, format=None): """ List all :class:`Relationship` instances. @@ -213,64 +144,3 @@ class RelationshipApiView(APIView): serializer = serializers.RelationshipSerializer(models.Relationship.objects.all(), many=True) return Response(serializer.data) - - -class NetworkView(LoginRequiredMixin, FormView): - """ - View to display relationship network. - """ - template_name = 'people/network.html' - form_class = forms.NetworkFilterForm - - def get_form_kwargs(self): - """ - Add GET params to form data. - """ - kwargs = super().get_form_kwargs() - - if self.request.method == 'GET': - if 'data' in kwargs: - kwargs['data'].update(self.request.GET) - - else: - kwargs['data'] = self.request.GET - - return kwargs - - def get_context_data(self, **kwargs): - """ - Add filtered QuerySets of :class:`Person` and :class:`Relationship` to the context. - """ - context = super().get_context_data(**kwargs) - form = context['form'] - - at_time = timezone.now() - - relationship_set = models.Relationship.objects.all() - - # Filter answers to relationship questions - for key, value in form.data.items(): - if key.startswith('question_') and value: - question_id = key.replace('question_', '', 1) - answer = models.RelationshipQuestionChoice.objects.get(pk=value, - question__pk=question_id) - relationship_set = relationship_set.filter( - Q(answer_sets__replaced_timestamp__gt=at_time) | Q(answer_sets__replaced_timestamp__isnull=True), - answer_sets__timestamp__lte=at_time, - answer_sets__question_answers=answer - ) - - context['person_set'] = serializers.PersonSerializer( - models.Person.objects.all(), - many=True - ).data - - context['relationship_set'] = serializers.RelationshipSerializer( - relationship_set, - many=True - ).data - - return context - - def form_valid(self, form): - return self.render_to_response(self.get_context_data())