Move form clean methods to models.

This commit is contained in:
Christopher Charbonneau Wells 2017-11-01 16:14:42 -04:00
parent 7d7148e869
commit 237796a644
3 changed files with 74 additions and 55 deletions

View File

@ -59,7 +59,8 @@ class ChildDeleteForm(forms.ModelForm):
def clean_confirm_name(self): def clean_confirm_name(self):
confirm_name = self.cleaned_data['confirm_name'] confirm_name = self.cleaned_data['confirm_name']
if confirm_name != str(self.instance): if confirm_name != str(self.instance):
raise forms.ValidationError('Name does not match child name.') raise forms.ValidationError(
'Name does not match child name.', code='confirm_mismatch')
return confirm_name return confirm_name
def save(self, commit=True): def save(self, commit=True):
@ -83,31 +84,6 @@ class DiaperChangeForm(forms.ModelForm):
kwargs = set_default_child(kwargs) kwargs = set_default_child(kwargs)
super(DiaperChangeForm, self).__init__(*args, **kwargs) super(DiaperChangeForm, self).__init__(*args, **kwargs)
def clean(self):
"""Additional form validation/cleaning.
"""
errors = {}
# One or both of Wet and Solid is required.
if not self.cleaned_data['wet'] and not self.cleaned_data['solid']:
errors['wet'] = forms.ValidationError(
'Wet and/or solid is required.',
code='missing-wet-or-solid')
errors['solid'] = forms.ValidationError(
'Wet and/or solid is required.',
code='missing-wet-or-solid')
# Color is required when Solid is selected.
if self.cleaned_data['solid'] and not self.cleaned_data['color']:
errors['color'] = forms.ValidationError(
'Color is required for solid changes.',
code='missing-color')
if len(errors) > 0:
raise forms.ValidationError(errors)
return self.cleaned_data
class FeedingForm(forms.ModelForm): class FeedingForm(forms.ModelForm):
class Meta: class Meta:
@ -130,23 +106,6 @@ class FeedingForm(forms.ModelForm):
kwargs = set_default_duration(kwargs) kwargs = set_default_duration(kwargs)
super(FeedingForm, self).__init__(*args, **kwargs) super(FeedingForm, self).__init__(*args, **kwargs)
def clean(self):
"""Additional form validation/cleaning.
"""
errors = {}
# "Formula" Type may only be associated with "Bottle" Method.
if (self.cleaned_data['type'] == 'formula'
and self.cleaned_data['method'] != 'bottle'):
errors['method'] = forms.ValidationError(
'Only "Bottle" method is allowed with type "Formula".',
code='bottle-formula-mismatch')
if len(errors) > 0:
raise forms.ValidationError(errors)
return self.cleaned_data
def save(self, commit=True): def save(self, commit=True):
instance = super(FeedingForm, self).save(commit=False) instance = super(FeedingForm, self).save(commit=False)
if self.timer_id: if self.timer_id:

View File

@ -19,10 +19,14 @@ def validate_duration(model, max_duration=timedelta(hours=24)):
""" """
if model.start and model.end: if model.start and model.end:
if model.start > model.end: if model.start > model.end:
raise ValidationError('Start time must come before end time') raise ValidationError(
'Start time must come before end time.',
code='end_before_start')
if model.end - model.start > max_duration: if model.end - model.start > max_duration:
raise ValidationError('Duration too long (%(timesince)s)', params={ raise ValidationError(
'timesince': timesince(model.start, model.end)}) 'Duration too long (%(timesince)s).',
params={'timesince': timesince(model.start, model.end)},
code='max_duration')
class Child(models.Model): class Child(models.Model):
@ -85,6 +89,18 @@ class DiaperChange(models.Model):
attributes.append(self.color) attributes.append(self.color)
return attributes return attributes
def clean(self):
# One or both of Wet and Solid is required.
if not self.wet and not self.solid:
raise ValidationError(
'Wet and/or solid is required.', code='wet_or_solid')
# Color is required when Solid is selected.
if self.solid and not self.color:
raise ValidationError(
{'color': 'Color is required for solid diaper changes.'},
code='solid_color_required')
class Feeding(models.Model): class Feeding(models.Model):
model_name = 'feeding' model_name = 'feeding'
@ -120,6 +136,13 @@ class Feeding(models.Model):
def clean(self): def clean(self):
validate_duration(self) validate_duration(self)
# "Formula" Type may only be associated with "Bottle" Method.
if self.type == 'formula'and self.method != 'bottle':
raise ValidationError(
{'method':
'Only "Bottle" method is allowed with "Formula" type.'},
code='bottle_formula_mismatch')
class Note(models.Model): class Note(models.Model):
model_name = 'note' model_name = 'note'

View File

@ -33,25 +33,54 @@ class FormsTestCase(TestCase):
cls.c.login(**cls.credentials) cls.c.login(**cls.credentials)
def test_child_forms(self): def test_child_forms(self):
entry = models.Child.objects.first() params = {
page = self.c.post('/children/{}/edit/'.format(entry.slug), {
'first_name': 'Child', 'first_name': 'Child',
'last_name': 'One', 'last_name': 'One',
'birth_date': '2000-01-01' 'birth_date': '2000-01-01'
}) }
entry = models.Child.objects.first()
page = self.c.post('/children/{}/edit/'.format(entry.slug), params)
self.assertEqual(page.status_code, 302)
entry.refresh_from_db()
params = {'confirm_name': 'Incorrect'}
page = self.c.post('/children/{}/delete/'.format(entry.slug), params)
self.assertEqual(page.status_code, 200)
self.assertFormError(page, 'form', 'confirm_name',
'Name does not match child name.')
params['confirm_name'] = str(entry)
page = self.c.post('/children/{}/delete/'.format(entry.slug), params)
self.assertEqual(page.status_code, 302) self.assertEqual(page.status_code, 302)
def test_diaperchange_forms(self): def test_diaperchange_forms(self):
entry = models.DiaperChange.objects.first() params = {
page = self.c.post('/changes/{}/'.format(entry.id), {
'child': 1, 'child': 1,
'time': '2000-01-01 1:01', 'time': '2000-01-01 1:01',
'wet': 1, 'wet': 1,
'solid': 1, 'solid': 1,
'color': 'black' 'color': 'black'
}) }
entry = models.DiaperChange.objects.first()
page = self.c.post('/changes/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 302) self.assertEqual(page.status_code, 302)
params['solid'] = 0
params['color'] = ''
page = self.c.post('/changes/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 200)
self.assertFormError(page, 'form', 'color',
'Color is required for solid diaper changes.')
del params['solid']
del params['wet']
page = self.c.post('/changes/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 200)
self.assertFormError(page, 'form', None,
'Wet and/or solid is required.')
def test_feeding_forms(self): def test_feeding_forms(self):
entry = models.Feeding.objects.first() entry = models.Feeding.objects.first()
params = { params = {
@ -75,7 +104,15 @@ class FormsTestCase(TestCase):
page = self.c.post('/feedings/{}/'.format(entry.id), params) page = self.c.post('/feedings/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 200) self.assertEqual(page.status_code, 200)
self.assertFormError(page, 'form', None, self.assertFormError(page, 'form', None,
'Start time must come before end time') 'Start time must come before end time.')
params['start'] = '2000-01-01 1:01'
params['method'] = 'left breast'
page = self.c.post('/feedings/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 200)
self.assertFormError(
page, 'form', 'method',
'Only "Bottle" method is allowed with "Formula" type.')
def test_sleeping_forms(self): def test_sleeping_forms(self):
params = { params = {
@ -97,7 +134,7 @@ class FormsTestCase(TestCase):
page = self.c.post('/sleep/{}/'.format(entry.id), params) page = self.c.post('/sleep/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 200) self.assertEqual(page.status_code, 200)
self.assertFormError(page, 'form', None, self.assertFormError(page, 'form', None,
'Start time must come before end time') 'Start time must come before end time.')
def test_timer_forms(self): def test_timer_forms(self):
timer = models.Timer.objects.create(user=self.user) timer = models.Timer.objects.create(user=self.user)
@ -143,4 +180,4 @@ class FormsTestCase(TestCase):
page = self.c.post('/tummy-time/{}/'.format(entry.id), params) page = self.c.post('/tummy-time/{}/'.format(entry.id), params)
self.assertEqual(page.status_code, 200) self.assertEqual(page.status_code, 200)
self.assertFormError(page, 'form', None, self.assertFormError(page, 'form', None,
'Start time must come before end time') 'Start time must come before end time.')