refactor: Split people.views into multiple modules

This commit is contained in:
James Graham
2020-03-27 15:15:18 +00:00
parent 7c75f9d7f4
commit 2cdc7675c7
5 changed files with 178 additions and 149 deletions

View File

@@ -7,46 +7,46 @@ app_name = 'people'
urlpatterns = [ urlpatterns = [
path('profile/', path('profile/',
views.ProfileView.as_view(), views.person.ProfileView.as_view(),
name='person.profile'), name='person.profile'),
path('people/create', path('people/create',
views.PersonCreateView.as_view(), views.person.PersonCreateView.as_view(),
name='person.create'), name='person.create'),
path('people', path('people',
views.PersonListView.as_view(), views.person.PersonListView.as_view(),
name='person.list'), name='person.list'),
path('people/<int:pk>', path('people/<int:pk>',
views.ProfileView.as_view(), views.person.ProfileView.as_view(),
name='person.detail'), name='person.detail'),
path('people/<int:pk>/update', path('people/<int:pk>/update',
views.PersonUpdateView.as_view(), views.person.PersonUpdateView.as_view(),
name='person.update'), name='person.update'),
path('people/<int:person_pk>/relationships/create', path('people/<int:person_pk>/relationships/create',
views.RelationshipCreateView.as_view(), views.relationship.RelationshipCreateView.as_view(),
name='person.relationship.create'), name='person.relationship.create'),
path('relationships/<int:pk>', path('relationships/<int:pk>',
views.RelationshipDetailView.as_view(), views.relationship.RelationshipDetailView.as_view(),
name='relationship.detail'), name='relationship.detail'),
path('relationships/<int:relationship_pk>/update', path('relationships/<int:relationship_pk>/update',
views.RelationshipUpdateView.as_view(), views.relationship.RelationshipUpdateView.as_view(),
name='relationship.update'), name='relationship.update'),
path('api/people', path('api/people',
views.PersonApiView.as_view(), views.person.PersonApiView.as_view(),
name='person.api.list'), name='person.api.list'),
path('api/relationships', path('api/relationships',
views.RelationshipApiView.as_view(), views.relationship.RelationshipApiView.as_view(),
name='relationship.api.list'), name='relationship.api.list'),
path('network', path('network',
views.NetworkView.as_view(), views.network.NetworkView.as_view(),
name='network'), name='network'),
] ]

9
people/views/__init__.py Normal file
View File

@@ -0,0 +1,9 @@
"""
Views for displaying or manipulating models within the `people` app.
"""
from . import (
network,
person,
relationship
)

72
people/views/network.py Normal file
View File

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

78
people/views/person.py Normal file
View File

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

View File

@@ -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.urls import reverse
from django.utils import timezone 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 rest_framework.views import APIView, Response
from . import forms, models, permissions, serializers 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 RelationshipDetailView(permissions.UserIsLinkedPersonMixin, DetailView): class RelationshipDetailView(permissions.UserIsLinkedPersonMixin, DetailView):
@@ -165,12 +108,12 @@ class RelationshipUpdateView(permissions.UserIsLinkedPersonMixin, CreateView):
context['relationship'] = self.relationship context['relationship'] = self.relationship
return context return context
def get_initial(self): def get_initial(self):
initial = super().get_initial() initial = super().get_initial()
initial['relationship'] = self.relationship initial['relationship'] = self.relationship
return initial return initial
def form_valid(self, form): def form_valid(self, form):
@@ -187,25 +130,13 @@ class RelationshipUpdateView(permissions.UserIsLinkedPersonMixin, CreateView):
answer_set.save() answer_set.save()
return response 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): class RelationshipApiView(APIView):
""" """
List all :class:`Relationship` instances. List all :class:`Relationship` instances.
""" """
def get(self, request, format=None): def get(self, request, format=None):
""" """
List all :class:`Relationship` instances. List all :class:`Relationship` instances.
@@ -213,64 +144,3 @@ class RelationshipApiView(APIView):
serializer = serializers.RelationshipSerializer(models.Relationship.objects.all(), serializer = serializers.RelationshipSerializer(models.Relationship.objects.all(),
many=True) many=True)
return Response(serializer.data) 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())