From 481ada74f825300ec30f8cd8c2dc4163f30e652e Mon Sep 17 00:00:00 2001 From: Christopher Charbonneau Wells Date: Sun, 13 Aug 2017 11:59:14 -0400 Subject: [PATCH] Add Feeding model. --- api/serializers.py | 20 +++++++++------ api/urls.py | 5 ++-- api/views.py | 20 +++++++++------ core/admin.py | 8 +++++- core/models.py | 61 +++++++++++++++++++++++---------------------- core/utils.py | 30 ++++++++++++++++++++++ db.sqlite3 | Bin 44032 -> 50176 bytes 7 files changed, 97 insertions(+), 47 deletions(-) create mode 100644 core/utils.py diff --git a/api/serializers.py b/api/serializers.py index 5a9b501c..58bcd900 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -4,13 +4,7 @@ from __future__ import unicode_literals from django.contrib.auth.models import User from rest_framework import serializers -from core.models import Baby, Sleep - - -class UserSerializer(serializers.HyperlinkedModelSerializer): - class Meta: - model = User - fields = ('url', 'username', 'email', 'is_staff') +from core.models import Baby, Feeding, Sleep class BabySerializer(serializers.HyperlinkedModelSerializer): @@ -19,7 +13,19 @@ class BabySerializer(serializers.HyperlinkedModelSerializer): fields = ('first_name', 'last_name', 'birth_date') +class FeedingSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = Feeding + fields = ('baby', 'start', 'end', 'duration', 'type', 'method') + + class SleepSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = Sleep fields = ('baby', 'start', 'end', 'duration') + + +class UserSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = User + fields = ('url', 'username', 'email', 'is_staff') diff --git a/api/urls.py b/api/urls.py index ef692326..5708fc46 100644 --- a/api/urls.py +++ b/api/urls.py @@ -1,13 +1,14 @@ from django.conf.urls import url, include from rest_framework import routers -from .views import UserViewSet, BabyViewSet, SleepViewSet +from .views import BabyViewSet, FeedingViewSet, SleepViewSet, UserViewSet # Routers provide an easy way of automatically determining the URL conf. router = routers.DefaultRouter() -router.register(r'users', UserViewSet) router.register(r'babies', BabyViewSet) +router.register(r'feedings', FeedingViewSet) router.register(r'sleep', SleepViewSet) +router.register(r'users', UserViewSet) # Wire up our API using automatic URL routing. # Additionally, we include login URLs for the browsable API. diff --git a/api/views.py b/api/views.py index 9baac326..cf147374 100644 --- a/api/views.py +++ b/api/views.py @@ -4,13 +4,9 @@ from __future__ import unicode_literals from django.contrib.auth.models import User from rest_framework import viewsets -from core.models import Baby, Sleep -from .serializers import (UserSerializer, BabySerializer, SleepSerializer) - - -class UserViewSet(viewsets.ModelViewSet): - queryset = User.objects.all() - serializer_class = UserSerializer +from core.models import Baby, Feeding, Sleep +from .serializers import (BabySerializer, FeedingSerializer, SleepSerializer, + UserSerializer,) class BabyViewSet(viewsets.ModelViewSet): @@ -18,6 +14,16 @@ class BabyViewSet(viewsets.ModelViewSet): serializer_class = BabySerializer +class FeedingViewSet(viewsets.ModelViewSet): + queryset = Feeding.objects.all() + serializer_class = FeedingSerializer + + class SleepViewSet(viewsets.ModelViewSet): queryset = Sleep.objects.all() serializer_class = SleepSerializer + + +class UserViewSet(viewsets.ModelViewSet): + queryset = User.objects.all() + serializer_class = UserSerializer diff --git a/core/admin.py b/core/admin.py index 07d2dd41..14599334 100644 --- a/core/admin.py +++ b/core/admin.py @@ -3,7 +3,7 @@ from __future__ import unicode_literals from django.contrib import admin -from .models import Baby, Sleep +from .models import Baby, Feeding, Sleep @admin.register(Baby) @@ -12,6 +12,12 @@ class BabyAdmin(admin.ModelAdmin): search_fields = ('first_name', 'last_name', 'birth_date',) +@admin.register(Feeding) +class FeedingAdmin(admin.ModelAdmin): + list_display = ('baby', 'start', 'end', 'duration', 'type', 'method',) + search_fields = ('baby__first_name', 'baby__last_name', 'type', 'method') + + @admin.register(Sleep) class SleepAdmin(admin.ModelAdmin): list_display = ('baby', 'start', 'end', 'duration',) diff --git a/core/models.py b/core/models.py index c8707465..7460a03d 100644 --- a/core/models.py +++ b/core/models.py @@ -1,11 +1,10 @@ # -*- coding: utf-8 -*- from __future__ import unicode_literals -from datetime import datetime -from math import floor - from django.db import models +from .utils import duration_string + class Baby(models.Model): first_name = models.CharField(max_length=255) @@ -23,6 +22,33 @@ class Baby(models.Model): return '{} {}'.format(self.first_name, self.last_name) +class Feeding(models.Model): + baby = models.ForeignKey('Baby', related_name='feeding') + start = models.DateTimeField(blank=False, null=False) + end = models.DateTimeField(blank=False, null=False) + type = models.CharField(max_length=255, choices=[ + ('breast milk', 'Breast milk'), + ('formula', 'Formula'), + ]) + method = models.CharField(max_length=255, choices=[ + ('bottle', 'Bottle'), + ('left breast', 'Left breast'), + ('right breast', 'Right breast'), + ]) + + objects = models.Manager() + + class Meta: + default_permissions = ('view', 'add', 'change', 'delete') + ordering = ['-start'] + + def __str__(self): + return '{} fed for {}'.format(self.baby, self.duration()) + + def duration(self): + return duration_string(self.start, self.end) + + class Sleep(models.Model): baby = models.ForeignKey('Baby', related_name='sleep') start = models.DateTimeField(blank=False, null=False) @@ -36,32 +62,7 @@ class Sleep(models.Model): verbose_name_plural = 'Sleep' def __str__(self): - return '{} slept for {}'.format( - self.baby, - self.duration() - ) + return '{} slept for {}'.format(self.baby, self.duration()) def duration(self): - diff = self.end - self.start - if diff.seconds < 60: - duration = '{} second{}'.format( - diff.seconds, - 's' if diff.seconds > 1 else '' - ) - elif diff.seconds < 3600: - duration = '{} minute{}, {} second{}'.format( - floor(diff.seconds / 60), - 's' if floor(diff.seconds / 60) > 1 else '', - diff.seconds % 60, - 's' if diff.seconds % 60 > 1 else '' - ) - else: - duration = '{} hour{}, {} minute{}, {} second{}'.format( - floor(diff.seconds / 3600), - 's' if floor(diff.seconds / 3600) > 1 else '', - floor((diff.seconds - 3600) / 60), - 's' if floor((diff.seconds - 3600) / 60) > 1 else '', - diff.seconds % 60, - 's' if diff.seconds % 60 > 1 else '' - ) - return duration + return duration_string(self.start, self.end) diff --git a/core/utils.py b/core/utils.py new file mode 100644 index 00000000..ee00f974 --- /dev/null +++ b/core/utils.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from math import floor + + +def duration_string(start, end): + diff = end - start + if diff.seconds < 60: + duration = '{} second{}'.format( + diff.seconds, + 's' if diff.seconds > 1 else '' + ) + elif diff.seconds < 3600: + duration = '{} minute{}, {} second{}'.format( + floor(diff.seconds / 60), + 's' if floor(diff.seconds / 60) > 1 else '', + diff.seconds % 60, + 's' if diff.seconds % 60 > 1 else '' + ) + else: + duration = '{} hour{}, {} minute{}, {} second{}'.format( + floor(diff.seconds / 3600), + 's' if floor(diff.seconds / 3600) > 1 else '', + floor((diff.seconds - 3600) / 60), + 's' if floor((diff.seconds - 3600) / 60) > 1 else '', + diff.seconds % 60, + 's' if diff.seconds % 60 > 1 else '' + ) + return duration diff --git a/db.sqlite3 b/db.sqlite3 index 37dd54ed8f09393e0b2fa846b16c7be2a4fc4289..ffe7077867cf9f7b7f507290d0f1085bc4b957fb 100644 GIT binary patch delta 1953 zcmbVNU2IcT96#s&?`?O-pzFRvw{mw!aSL6!AMLu{nYa(9m>{5GhRBwt_!FAtrQvAt1&?iKq|w-~$riK}^&{L@;8^Nc7y>mUM$BZ`$8I z_kVup|9SrB9JxjvIS!{>&R&F&So~x1-ktTzt-Yx8-g$<6RlqfZ$Ore}NB9kXhGlpF zH{n`N-vjbf3Yqeli|y3}>KX~O))HVU32fL%U_EDQ!LUpa39y`ZHs6I7w8gO&!bJH? z0GHtgoP=|5pL~qL9L(kPAoNtNg$?Z9WJ(KqT(^|@mjD-;dzr(k19WKEcNWcgjf)l2Lr6>1x z5S-O?z02~p=op(%INqhfjV~DXxGdajNlIZ0N=o;@FBcOvO5XGIlUj8 z4wgpsE;E%yWBJLR_lR$>)3EmjDqs|b;T71K)2pC~0gPFSHVF8i)|(_CeZo& z^EHHuhY*~HXQ(UG5WbFwa(W+Tb;`yf#{?cTK0nrw;G&w!MUyEm$dPJIXSB4J^K)r! zZ!)2#sXcRiA$KaTaC3Y#rp47X8SddT2d6aN%kh(1W<06#BZm)^cUK&fJKv0!3Y>eEFJF z_c4XMS-suxe(-&sGXACA=pRI(W<>2H(2W1UHKmP>kp8M-_!bhBmN2r}M&rAMps~2% zVmcs%_h2Z;`88b*;O_qbJ$g&~`1jvKnDDnUqWc%v-Uw8M~8$BNU#(X9+8YfLdPTQh$f zp=t-pHCe}eIHraL$sdhKQMr7wz39OU+n*iWz0!ln*74kq?JFrf*Up=lNZ1xr`HllU zM*rf0B^uLfNUkY3j^Il;PO^On<`pM{>U;W3(}E!Q!{pFUhRrk!-J%>8#lY&E3ubGD r{9-U9Db?j`<;T|gyH?iA-=#<)pD4?6mwADjk9kv~cB?zGJDL9g0`~|R delta 637 zcmZXRPiRv?5XN`+dm(>mO-&V3FbPzwB(X_eN=g)r)QjN3OFf7X5*yOkycbDYtf<&` zk*WpzT+mX47W5!`N%DloswXc&5idPhwTL2kQA;E0A%bp{9E!v22Q%M~VVIqo#?&h| z+vAK8Lj2;jBcTUmPmBaNY9`S#W36TE#s)s%Gd`h-A6PS-QX1Y}{ViaN5Z87gzO6z` zHX)u~A#QKAMx}0C5Hpg%6THPW+(knag^G3Xv&|Js{tP_04I-25O@BbO!&NwAu zGzfm-CmO=|2%~YaOEg)XpoRmiUeT7BQNOg`+5sX?*-Kx7;Sn1%x@H@cQe8X5=tEsw zG8q3YIjM!1#1G;r0(6=9X+l4^1KRN@_spsM)`KzA9(I`w>ROad4)E!vNoYr8uFUVG zeSBuVOmFMj0^fUmrCO$vK^N~~Shhw&;aD&<7!1qaa5Nqb$0OnYTM<7s5qUE#$3r2J Wn_)Q?k3_0>B*~D