Add validation for model durations

It was previously possible to accidentally enter obviously wrong values
for start/end dates. Add some basic validation to catch input errors
when creating or editing various models (when not using a timer).
This commit is contained in:
Bob Thomas 2017-11-01 12:44:07 -04:00
parent 40f8a511ba
commit 1eeba2398d
2 changed files with 49 additions and 0 deletions

View File

@ -1,9 +1,28 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from datetime import timedelta
from django.core.exceptions import ValidationError
from django.db import models
from django.template.defaultfilters import slugify
from django.utils import timezone
from django.utils.timesince import timesince
def validate_duration(model, max_duration=timedelta(hours=24)):
"""
Basic sanity checks for models with a duration
:param model: a model instance with 'start' and 'end' attributes
:param max_duration: maximum allowed duration between start and end time
:return:
"""
if model.start and model.end:
if model.start > model.end:
raise ValidationError('Start time must come before end time')
if model.end - model.start > max_duration:
raise ValidationError('Duration too long (%(timesince)s)', params={
'timesince': timesince(model.start, model.end)})
class Child(models.Model):
@ -98,6 +117,9 @@ class Feeding(models.Model):
self.duration = self.end - self.start
super(Feeding, self).save(*args, **kwargs)
def clean(self):
validate_duration(self)
class Note(models.Model):
model_name = 'note'
@ -137,6 +159,9 @@ class Sleep(models.Model):
self.duration = self.end - self.start
super(Sleep, self).save(*args, **kwargs)
def clean(self):
validate_duration(self)
class Timer(models.Model):
model_name = 'timer'
@ -191,6 +216,9 @@ class Timer(models.Model):
self.duration = None
super(Timer, self).save(*args, **kwargs)
def clean(self):
validate_duration(self)
class TummyTime(models.Model):
model_name = 'tummytime'
@ -213,3 +241,6 @@ class TummyTime(models.Model):
if self.start and self.end:
self.duration = self.end - self.start
super(TummyTime, self).save(*args, **kwargs)
def clean(self):
validate_duration(self)

View File

@ -71,6 +71,12 @@ class FormsTestCase(TestCase):
page = self.c.post('/feedings/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 302)
params['start'] = '2001-01-01 1:01'
page = self.c.post('/feedings/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 200)
self.assertFormError(page, 'form', None,
'Start time must come before end time')
def test_sleeping_forms(self):
params = {
'child': 1,
@ -87,6 +93,12 @@ class FormsTestCase(TestCase):
page = self.c.post('/sleep/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 302)
params['start'] = '2001-01-01 1:01'
page = self.c.post('/sleep/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 200)
self.assertFormError(page, 'form', None,
'Start time must come before end time')
def test_timer_forms(self):
timer = models.Timer.objects.create(user=self.user)
timer.save()
@ -126,3 +138,9 @@ class FormsTestCase(TestCase):
entry = models.TummyTime.objects.first()
page = self.c.post('/tummy-time/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 302)
params['start'] = '2001-01-01 1:01'
page = self.c.post('/tummy-time/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 200)
self.assertFormError(page, 'form', None,
'Start time must come before end time')