2017-08-13 13:44:48 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
2020-03-14 03:00:32 +00:00
|
|
|
from copy import deepcopy
|
2017-08-13 13:44:48 +00:00
|
|
|
from rest_framework import serializers
|
2020-03-14 05:17:24 +00:00
|
|
|
from rest_framework.exceptions import ValidationError
|
2017-08-13 13:44:48 +00:00
|
|
|
|
2017-10-21 21:35:34 +00:00
|
|
|
from django.contrib.auth.models import User
|
2020-03-14 05:17:24 +00:00
|
|
|
from django.utils import timezone
|
2017-10-21 21:35:34 +00:00
|
|
|
|
2017-11-10 02:15:09 +00:00
|
|
|
from core import models
|
2017-08-13 14:48:16 +00:00
|
|
|
|
|
|
|
|
2017-12-05 21:31:37 +00:00
|
|
|
class CoreModelSerializer(serializers.HyperlinkedModelSerializer):
|
|
|
|
"""
|
|
|
|
Provide the child link (used by most core models) and run model clean()
|
|
|
|
methods during POST operations.
|
|
|
|
"""
|
|
|
|
child = serializers.PrimaryKeyRelatedField(
|
|
|
|
queryset=models.Child.objects.all())
|
|
|
|
|
|
|
|
def validate(self, attrs):
|
2020-03-14 03:00:32 +00:00
|
|
|
# Ensure that all instance data is available for partial updates to
|
|
|
|
# support clean methods that compare multiple fields.
|
|
|
|
if self.partial:
|
|
|
|
new_instance = deepcopy(self.instance)
|
|
|
|
for attr, value in attrs.items():
|
|
|
|
setattr(new_instance, attr, value)
|
|
|
|
else:
|
|
|
|
new_instance = self.Meta.model(**attrs)
|
|
|
|
new_instance.clean()
|
2017-12-05 21:31:37 +00:00
|
|
|
return attrs
|
|
|
|
|
|
|
|
|
2020-03-14 05:17:24 +00:00
|
|
|
class CoreModelWithDurationSerializer(CoreModelSerializer):
|
|
|
|
"""
|
|
|
|
Specific serializer base for models with a "start" and "end" field.
|
|
|
|
"""
|
|
|
|
child = serializers.PrimaryKeyRelatedField(
|
|
|
|
allow_null=True, allow_empty=True, queryset=models.Child.objects.all(),
|
|
|
|
required=False)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
abstract = True
|
|
|
|
extra_kwargs = {
|
|
|
|
'start': {'required': False},
|
|
|
|
'end': {'required': False},
|
|
|
|
}
|
|
|
|
|
|
|
|
def validate(self, attrs):
|
|
|
|
# Check for a special "timer" data argument that can be used in place
|
|
|
|
# of "start" and "end" fields as well as "child" if it is set on the
|
|
|
|
# Timer entry.
|
|
|
|
timer = None
|
|
|
|
if 'timer' in self.initial_data:
|
|
|
|
try:
|
|
|
|
timer = models.Timer.objects.get(pk=self.initial_data['timer'])
|
|
|
|
except models.Timer.DoesNotExist:
|
|
|
|
raise ValidationError({'timer': ['Timer does not exist.']})
|
|
|
|
if timer.end:
|
|
|
|
end = timer.end
|
|
|
|
else:
|
|
|
|
end = timezone.now()
|
2020-03-14 20:24:00 +00:00
|
|
|
if timer.child:
|
2020-03-14 05:17:24 +00:00
|
|
|
attrs['child'] = timer.child
|
|
|
|
|
|
|
|
# Overwrites values provided directly!
|
|
|
|
attrs['start'] = timer.start
|
|
|
|
attrs['end'] = end
|
|
|
|
|
|
|
|
# The "child", "start", and "end" field should all be set at this
|
|
|
|
# point. If one is not, model validation will fail because they are
|
|
|
|
# required fields at the model level.
|
|
|
|
if not self.partial:
|
|
|
|
errors = {}
|
|
|
|
for field in ['child', 'start', 'end']:
|
|
|
|
if field not in attrs or not attrs[field]:
|
|
|
|
errors[field] = 'This field is required.'
|
|
|
|
if len(errors) > 0:
|
|
|
|
raise ValidationError(errors)
|
|
|
|
|
|
|
|
attrs = super().validate(attrs)
|
|
|
|
|
|
|
|
# Only actually stop the timer if all validation passed.
|
|
|
|
if timer:
|
|
|
|
timer.stop(attrs['end'])
|
|
|
|
|
|
|
|
return attrs
|
|
|
|
|
|
|
|
|
2017-10-21 21:35:34 +00:00
|
|
|
class UserSerializer(serializers.ModelSerializer):
|
|
|
|
class Meta:
|
|
|
|
model = User
|
|
|
|
fields = ('id', 'username')
|
|
|
|
|
|
|
|
|
2017-08-16 12:49:58 +00:00
|
|
|
class ChildSerializer(serializers.HyperlinkedModelSerializer):
|
2017-08-13 14:48:16 +00:00
|
|
|
class Meta:
|
2017-11-10 02:15:09 +00:00
|
|
|
model = models.Child
|
2020-01-30 21:55:33 +00:00
|
|
|
fields = ('id', 'first_name', 'last_name', 'birth_date', 'slug',
|
|
|
|
'picture')
|
2017-08-18 12:08:23 +00:00
|
|
|
lookup_field = 'slug'
|
2017-08-13 14:48:16 +00:00
|
|
|
|
|
|
|
|
2017-12-05 21:31:37 +00:00
|
|
|
class DiaperChangeSerializer(CoreModelSerializer):
|
2017-08-13 19:51:25 +00:00
|
|
|
class Meta:
|
2017-11-10 02:15:09 +00:00
|
|
|
model = models.DiaperChange
|
2021-02-09 19:04:35 +00:00
|
|
|
fields = (
|
|
|
|
'id',
|
|
|
|
'child',
|
|
|
|
'time',
|
|
|
|
'wet',
|
|
|
|
'solid',
|
|
|
|
'color',
|
|
|
|
'amount',
|
|
|
|
'notes'
|
|
|
|
)
|
2017-08-13 19:51:25 +00:00
|
|
|
|
2017-08-17 16:17:51 +00:00
|
|
|
|
2020-03-14 05:17:24 +00:00
|
|
|
class FeedingSerializer(CoreModelWithDurationSerializer):
|
|
|
|
class Meta(CoreModelWithDurationSerializer.Meta):
|
2017-11-10 02:15:09 +00:00
|
|
|
model = models.Feeding
|
2017-12-05 21:31:37 +00:00
|
|
|
fields = ('id', 'child', 'start', 'end', 'duration', 'type', 'method',
|
2021-02-09 18:31:07 +00:00
|
|
|
'amount', 'notes')
|
2017-08-13 15:59:14 +00:00
|
|
|
|
|
|
|
|
2017-12-05 21:31:37 +00:00
|
|
|
class NoteSerializer(CoreModelSerializer):
|
2017-08-13 20:48:16 +00:00
|
|
|
class Meta:
|
2017-11-10 02:15:09 +00:00
|
|
|
model = models.Note
|
2017-12-05 21:31:37 +00:00
|
|
|
fields = ('id', 'child', 'note', 'time')
|
2017-08-13 20:48:16 +00:00
|
|
|
|
2017-08-17 16:17:51 +00:00
|
|
|
|
2020-03-14 05:17:24 +00:00
|
|
|
class SleepSerializer(CoreModelWithDurationSerializer):
|
|
|
|
class Meta(CoreModelWithDurationSerializer.Meta):
|
2017-11-10 02:15:09 +00:00
|
|
|
model = models.Sleep
|
2021-02-09 18:31:07 +00:00
|
|
|
fields = ('id', 'child', 'start', 'end', 'duration', 'nap', 'notes')
|
2017-08-13 15:59:14 +00:00
|
|
|
|
|
|
|
|
2019-05-17 05:13:14 +00:00
|
|
|
class TemperatureSerializer(CoreModelSerializer):
|
|
|
|
class Meta:
|
|
|
|
model = models.Temperature
|
2021-02-09 18:31:07 +00:00
|
|
|
fields = ('id', 'child', 'temperature', 'time', 'notes')
|
2019-05-17 05:13:14 +00:00
|
|
|
|
|
|
|
|
2017-12-05 21:31:37 +00:00
|
|
|
class TimerSerializer(CoreModelSerializer):
|
2020-01-30 21:55:33 +00:00
|
|
|
child = serializers.PrimaryKeyRelatedField(
|
|
|
|
allow_null=True, allow_empty=True, queryset=models.Child.objects.all(),
|
|
|
|
required=False)
|
2020-06-19 21:23:43 +00:00
|
|
|
user = serializers.PrimaryKeyRelatedField(
|
|
|
|
allow_null=True, allow_empty=True, queryset=User.objects.all(),
|
|
|
|
required=False)
|
2017-10-21 21:35:34 +00:00
|
|
|
|
2017-08-16 22:33:02 +00:00
|
|
|
class Meta:
|
2017-11-10 02:15:09 +00:00
|
|
|
model = models.Timer
|
2020-01-30 21:55:33 +00:00
|
|
|
fields = ('id', 'child', 'name', 'start', 'end', 'duration', 'active',
|
|
|
|
'user')
|
2017-08-16 22:33:02 +00:00
|
|
|
|
2020-06-19 21:23:43 +00:00
|
|
|
def validate(self, attrs):
|
|
|
|
attrs = super(TimerSerializer, self).validate(attrs)
|
|
|
|
|
|
|
|
# Set user to current user if no value is provided.
|
|
|
|
if 'user' not in attrs or attrs['user'] is None:
|
|
|
|
attrs['user'] = self.context['request'].user
|
|
|
|
|
|
|
|
return attrs
|
|
|
|
|
2017-08-16 22:33:02 +00:00
|
|
|
|
2020-03-14 05:17:24 +00:00
|
|
|
class TummyTimeSerializer(CoreModelWithDurationSerializer):
|
|
|
|
class Meta(CoreModelWithDurationSerializer.Meta):
|
2017-11-10 02:15:09 +00:00
|
|
|
model = models.TummyTime
|
2017-12-05 21:31:37 +00:00
|
|
|
fields = ('id', 'child', 'start', 'end', 'duration', 'milestone')
|
2017-11-10 02:15:09 +00:00
|
|
|
|
|
|
|
|
2017-12-05 21:31:37 +00:00
|
|
|
class WeightSerializer(CoreModelSerializer):
|
2017-11-10 02:15:09 +00:00
|
|
|
class Meta:
|
|
|
|
model = models.Weight
|
2021-02-09 18:31:07 +00:00
|
|
|
fields = ('id', 'child', 'weight', 'date', 'notes')
|