mybuddy/core/views.py

559 lines
18 KiB
Python

# -*- coding: utf-8 -*-
from django.contrib import messages
from django.contrib.messages.views import SuccessMessageMixin
from django.forms import Form
from django.http import HttpResponseRedirect
from django.urls import reverse, reverse_lazy
from django.utils import timezone
from django.utils.translation import gettext as _
from django.views.generic.base import RedirectView, TemplateView
from django.views.generic.detail import DetailView
from django.views.generic.edit import CreateView, UpdateView, DeleteView, \
FormView
from babybuddy.mixins import LoginRequiredMixin, PermissionRequiredMixin
from babybuddy.views import BabyBuddyFilterView
from core import forms, models, timeline
def _prepare_timeline_context_data(context, date, child=None):
date = timezone.datetime.strptime(date, '%Y-%m-%d')
date = timezone.localtime(timezone.make_aware(date))
context['timeline_objects'] = timeline.get_objects(date, child)
context['date'] = date
context['date_previous'] = date - timezone.timedelta(days=1)
if date.date() < timezone.localdate():
context['date_next'] = date + timezone.timedelta(days=1)
pass
class CoreAddView(PermissionRequiredMixin, SuccessMessageMixin, CreateView):
def get_success_message(self, cleaned_data):
cleaned_data['model'] = self.model._meta.verbose_name.title()
if 'child' in cleaned_data:
self.success_message = _('%(model)s entry for %(child)s added!')
else:
self.success_message = _('%(model)s entry added!')
return self.success_message % cleaned_data
def get_form_kwargs(self):
"""
Check for and add "child" and "timer" from request query parameters.
- "child" may provide a slug for a Child instance.
- "timer" may provided an ID for a Timer instance.
These arguments are used in some add views to pre-fill initial data in
the form fields.
:return: Updated keyword arguments.
"""
kwargs = super(CoreAddView, self).get_form_kwargs()
for parameter in ['child', 'timer']:
value = self.request.GET.get(parameter, None)
if value:
kwargs.update({parameter: value})
return kwargs
class CoreUpdateView(PermissionRequiredMixin, SuccessMessageMixin,
UpdateView):
def get_success_message(self, cleaned_data):
cleaned_data['model'] = self.model._meta.verbose_name.title()
if 'child' in cleaned_data:
self.success_message = _('%(model)s entry for %(child)s updated.')
else:
self.success_message = _('%(model)s entry updated.')
return self.success_message % cleaned_data
class CoreDeleteView(PermissionRequiredMixin, DeleteView):
"""
SuccessMessageMixin is not compatible DeleteView.
See: https://code.djangoproject.com/ticket/21936
"""
def delete(self, request, *args, **kwargs):
success_message = _('%(model)s entry deleted.') % {
'model': self.model._meta.verbose_name.title()
}
messages.success(request, success_message)
return super(CoreDeleteView, self).delete(request, *args, **kwargs)
class ChildList(PermissionRequiredMixin, BabyBuddyFilterView):
model = models.Child
template_name = 'core/child_list.html'
permission_required = ('core.view_child',)
paginate_by = 10
filterset_fields = ('first_name', 'last_name')
class ChildAdd(CoreAddView):
model = models.Child
permission_required = ('core.add_child',)
form_class = forms.ChildForm
success_url = reverse_lazy('core:child-list')
success_message = _('%(first_name)s %(last_name)s added!')
class ChildDetail(PermissionRequiredMixin, DetailView):
model = models.Child
permission_required = ('core.view_child',)
def get_context_data(self, **kwargs):
context = super(ChildDetail, self).get_context_data(**kwargs)
date = self.request.GET.get('date', str(timezone.localdate()))
_prepare_timeline_context_data(context, date, self.object)
return context
class ChildUpdate(CoreUpdateView):
model = models.Child
permission_required = ('core.change_child',)
form_class = forms.ChildForm
success_url = reverse_lazy('core:child-list')
class ChildDelete(CoreUpdateView):
model = models.Child
form_class = forms.ChildDeleteForm
template_name = 'core/child_confirm_delete.html'
permission_required = ('core.delete_child',)
success_url = reverse_lazy('core:child-list')
def get_success_message(self, cleaned_data):
""" This class cannot use `CoreDeleteView` because of the confirmation
step required so the success message must be overridden."""
success_message = _('%(model)s entry deleted.') % {
'model': self.model._meta.verbose_name.title()
}
return success_message % cleaned_data
class DiaperChangeList(PermissionRequiredMixin, BabyBuddyFilterView):
model = models.DiaperChange
template_name = 'core/diaperchange_list.html'
permission_required = ('core.view_diaperchange',)
paginate_by = 10
filterset_fields = ('child', 'wet', 'solid', 'color')
class DiaperChangeAdd(CoreAddView):
model = models.DiaperChange
permission_required = ('core.add_diaperchange',)
form_class = forms.DiaperChangeForm
success_url = reverse_lazy('core:diaperchange-list')
class DiaperChangeUpdate(CoreUpdateView):
model = models.DiaperChange
permission_required = ('core.change_diaperchange',)
form_class = forms.DiaperChangeForm
success_url = reverse_lazy('core:diaperchange-list')
class DiaperChangeDelete(CoreDeleteView):
model = models.DiaperChange
permission_required = ('core.delete_diaperchange',)
success_url = reverse_lazy('core:diaperchange-list')
class FeedingList(PermissionRequiredMixin, BabyBuddyFilterView):
model = models.Feeding
template_name = 'core/feeding_list.html'
permission_required = ('core.view_feeding',)
paginate_by = 10
filterset_fields = ('child', 'type', 'method')
class FeedingAdd(CoreAddView):
model = models.Feeding
permission_required = ('core.add_feeding',)
form_class = forms.FeedingForm
success_url = reverse_lazy('core:feeding-list')
class FeedingUpdate(CoreUpdateView):
model = models.Feeding
permission_required = ('core.change_feeding',)
form_class = forms.FeedingForm
success_url = reverse_lazy('core:feeding-list')
class FeedingDelete(CoreDeleteView):
model = models.Feeding
permission_required = ('core.delete_feeding',)
success_url = reverse_lazy('core:feeding-list')
class NoteList(PermissionRequiredMixin, BabyBuddyFilterView):
model = models.Note
template_name = 'core/note_list.html'
permission_required = ('core.view_note',)
paginate_by = 10
filterset_fields = ('child',)
class NoteAdd(CoreAddView):
model = models.Note
permission_required = ('core.add_note',)
form_class = forms.NoteForm
success_url = reverse_lazy('core:note-list')
class NoteUpdate(CoreUpdateView):
model = models.Note
permission_required = ('core.change_note',)
form_class = forms.NoteForm
success_url = reverse_lazy('core:note-list')
class NoteDelete(CoreDeleteView):
model = models.Note
permission_required = ('core.delete_note',)
success_url = reverse_lazy('core:note-list')
class SleepList(PermissionRequiredMixin, BabyBuddyFilterView):
model = models.Sleep
template_name = 'core/sleep_list.html'
permission_required = ('core.view_sleep',)
paginate_by = 10
filterset_fields = ('child',)
class SleepAdd(CoreAddView):
model = models.Sleep
permission_required = ('core.add_sleep',)
form_class = forms.SleepForm
success_url = reverse_lazy('core:sleep-list')
class SleepUpdate(CoreUpdateView):
model = models.Sleep
permission_required = ('core.change_sleep',)
form_class = forms.SleepForm
success_url = reverse_lazy('core:sleep-list')
class SleepDelete(CoreDeleteView):
model = models.Sleep
permission_required = ('core.delete_sleep',)
success_url = reverse_lazy('core:sleep-list')
class TemperatureList(PermissionRequiredMixin, BabyBuddyFilterView):
model = models.Temperature
template_name = 'core/temperature_list.html'
permission_required = ('core.view_temperature',)
paginate_by = 10
filterset_fields = ('child',)
class TemperatureAdd(CoreAddView):
model = models.Temperature
permission_required = ('core.add_temperature',)
form_class = forms.TemperatureForm
success_url = reverse_lazy('core:temperature-list')
success_message = _('%(model)s reading added!')
class TemperatureUpdate(CoreUpdateView):
model = models.Temperature
permission_required = ('core.change_temperature',)
form_class = forms.TemperatureForm
success_url = reverse_lazy('core:temperature-list')
success_message = _('%(model)s reading for %(child)s updated.')
class TemperatureDelete(CoreDeleteView):
model = models.Temperature
permission_required = ('core.delete_temperature',)
success_url = reverse_lazy('core:temperature-list')
class Timeline(LoginRequiredMixin, TemplateView):
template_name = 'timeline/timeline.html'
# Show the overall timeline or a child timeline if one Child instance.
def get(self, request, *args, **kwargs):
children = models.Child.objects.count()
if children == 1:
return HttpResponseRedirect(
reverse(
'core:child',
args={models.Child.objects.first().slug}
)
)
return super(Timeline, self).get(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(Timeline, self).get_context_data(**kwargs)
date = self.request.GET.get('date', str(timezone.localdate()))
_prepare_timeline_context_data(context, date)
return context
class TimerList(PermissionRequiredMixin, BabyBuddyFilterView):
model = models.Timer
template_name = 'core/timer_list.html'
permission_required = ('core.view_timer',)
paginate_by = 10
filterset_fields = ('active', 'user')
class TimerDetail(PermissionRequiredMixin, DetailView):
model = models.Timer
permission_required = ('core.view_timer',)
class TimerAdd(PermissionRequiredMixin, CreateView):
model = models.Timer
permission_required = ('core.add_timer',)
form_class = forms.TimerForm
def get_form_kwargs(self):
kwargs = super(TimerAdd, self).get_form_kwargs()
kwargs.update({'user': self.request.user})
return kwargs
def get_success_url(self):
return reverse('core:timer-detail', kwargs={'pk': self.object.pk})
class TimerUpdate(CoreUpdateView):
model = models.Timer
permission_required = ('core.change_timer',)
form_class = forms.TimerForm
success_url = reverse_lazy('core:timer-list')
def get_form_kwargs(self):
kwargs = super(TimerUpdate, self).get_form_kwargs()
kwargs.update({'user': self.request.user})
return kwargs
def get_success_url(self):
instance = self.get_object()
return reverse('core:timer-detail', kwargs={'pk': instance.pk})
class TimerAddQuick(PermissionRequiredMixin, RedirectView):
http_method_names = ['post']
permission_required = ('core.add_timer',)
def post(self, request, *args, **kwargs):
instance = models.Timer.objects.create(user=request.user)
# Add child relationship if there is only Child instance.
if models.Child.count() == 1:
instance.child = models.Child.objects.first()
instance.save()
self.url = request.GET.get(
'next', reverse('core:timer-detail', args={instance.id}))
return super(TimerAddQuick, self).get(request, *args, **kwargs)
class TimerRestart(PermissionRequiredMixin, RedirectView):
http_method_names = ['post']
permission_required = ('core.change_timer',)
def post(self, request, *args, **kwargs):
instance = models.Timer.objects.get(id=kwargs['pk'])
instance.restart()
messages.success(request, '{} restarted.'.format(instance))
return super(TimerRestart, self).get(request, *args, **kwargs)
def get_redirect_url(self, *args, **kwargs):
return reverse('core:timer-detail', kwargs={'pk': kwargs['pk']})
class TimerStop(PermissionRequiredMixin, SuccessMessageMixin, RedirectView):
http_method_names = ['post']
permission_required = ('core.change_timer',)
success_message = _('%(timer)s stopped.')
def post(self, request, *args, **kwargs):
instance = models.Timer.objects.get(id=kwargs['pk'])
instance.stop()
messages.success(request, '{} stopped.'.format(instance))
return super(TimerStop, self).get(request, *args, **kwargs)
def get_redirect_url(self, *args, **kwargs):
return reverse('core:timer-detail', kwargs={'pk': kwargs['pk']})
class TimerDelete(CoreDeleteView):
model = models.Timer
permission_required = ('core.delete_timer',)
success_url = reverse_lazy('core:timer-list')
class TimerDeleteInactive(PermissionRequiredMixin, SuccessMessageMixin,
FormView):
permission_required = ('core.delete_timer',)
form_class = Form
template_name = 'core/timer_confirm_delete_inactive.html'
success_url = reverse_lazy('core:timer-list')
success_message = _('All inactive timers deleted.')
def get_context_data(self, **kwargs):
kwargs = super().get_context_data(**kwargs)
kwargs['timer_count'] = self.get_instances().count()
return kwargs
def get(self, request, *args, **kwargs):
# Redirect back to list if there are no inactive timers.
if self.get_instances().count() == 0:
messages.warning(request, _('No inactive timers exist.'))
return HttpResponseRedirect(self.success_url)
return super().get(request, *args, **kwargs)
def form_valid(self, form):
self.get_instances().delete()
return super().form_valid(form)
@staticmethod
def get_instances():
return models.Timer.objects.filter(active=False)
class TummyTimeList(PermissionRequiredMixin, BabyBuddyFilterView):
model = models.TummyTime
template_name = 'core/tummytime_list.html'
permission_required = ('core.view_tummytime',)
paginate_by = 10
filterset_fields = ('child',)
class TummyTimeAdd(CoreAddView):
model = models.TummyTime
permission_required = ('core.add_tummytime',)
form_class = forms.TummyTimeForm
success_url = reverse_lazy('core:tummytime-list')
class TummyTimeUpdate(CoreUpdateView):
model = models.TummyTime
permission_required = ('core.change_tummytime',)
form_class = forms.TummyTimeForm
success_url = reverse_lazy('core:tummytime-list')
class TummyTimeDelete(CoreDeleteView):
model = models.TummyTime
permission_required = ('core.delete_tummytime',)
success_url = reverse_lazy('core:tummytime-list')
class WeightList(PermissionRequiredMixin, BabyBuddyFilterView):
model = models.Weight
template_name = 'core/weight_list.html'
permission_required = ('core.view_weight',)
paginate_by = 10
filterset_fields = ('child',)
class WeightAdd(CoreAddView):
model = models.Weight
permission_required = ('core.add_weight',)
form_class = forms.WeightForm
success_url = reverse_lazy('core:weight-list')
class WeightUpdate(CoreUpdateView):
model = models.Weight
permission_required = ('core.change_weight',)
form_class = forms.WeightForm
success_url = reverse_lazy('core:weight-list')
class WeightDelete(CoreDeleteView):
model = models.Weight
permission_required = ('core.delete_weight',)
success_url = reverse_lazy('core:weight-list')
class HeightList(PermissionRequiredMixin, BabyBuddyFilterView):
model = models.Height
template_name = 'core/height_list.html'
permission_required = ('core.view_height',)
paginate_by = 10
filterset_fields = ('child',)
class HeightAdd(CoreAddView):
model = models.Height
permission_required = ('core.add_height',)
form_class = forms.HeightForm
success_url = reverse_lazy('core:height-list')
class HeightUpdate(CoreUpdateView):
model = models.Height
permission_required = ('core.change_height',)
form_class = forms.HeightForm
success_url = reverse_lazy('core:height-list')
class HeightDelete(CoreDeleteView):
model = models.Height
permission_required = ('core.delete_height',)
success_url = reverse_lazy('core:height-list')
class HeadCircumferenceList(PermissionRequiredMixin, BabyBuddyFilterView):
model = models.HeadCircumference
template_name = 'core/head_circumference_list.html'
permission_required = ('core.view_head_circumference',)
paginate_by = 10
filterset_fields = ('child',)
class HeadCircumferenceAdd(CoreAddView):
model = models.HeadCircumference
template_name = 'core/head_circumference_form.html'
permission_required = ('core.add_head_circumference',)
form_class = forms.HeadCircumferenceForm
success_url = reverse_lazy('core:head-circumference-list')
class HeadCircumferenceUpdate(CoreUpdateView):
model = models.HeadCircumference
template_name = 'core/head_circumference_form.html'
permission_required = ('core.change_head_circumference',)
form_class = forms.HeadCircumferenceForm
success_url = reverse_lazy('core:head-circumference-list')
class HeadCircumferenceDelete(CoreDeleteView):
model = models.HeadCircumference
template_name = 'core/head_circumference_delete.html'
permission_required = ('core.delete_head_circumference',)
success_url = reverse_lazy('core:head-circumference-list')
class BMIList(PermissionRequiredMixin, BabyBuddyFilterView):
model = models.BMI
template_name = 'core/bmi_list.html'
permission_required = ('core.view_bmi',)
paginate_by = 10
filterset_fields = ('child',)
class BMIAdd(CoreAddView):
model = models.BMI
permission_required = ('core.add_bmi',)
form_class = forms.BMIForm
success_url = reverse_lazy('core:bmi-list')
class BMIUpdate(CoreUpdateView):
model = models.BMI
permission_required = ('core.change_bmi',)
form_class = forms.BMIForm
success_url = reverse_lazy('core:bmi-list')
class BMIDelete(CoreDeleteView):
model = models.BMI
permission_required = ('core.delete_bmi',)
success_url = reverse_lazy('core:bmi-list')