Add birth time support to Child model

This commit is contained in:
Christopher C. Wells 2023-10-21 11:16:08 -07:00 committed by Christopher Charbonneau Wells
parent 0077d26142
commit 39c1e98d8c
13 changed files with 1105 additions and 23 deletions

View File

@ -126,7 +126,15 @@ class PumpingSerializer(CoreModelSerializer, TaggableSerializer):
class ChildSerializer(serializers.HyperlinkedModelSerializer): class ChildSerializer(serializers.HyperlinkedModelSerializer):
class Meta: class Meta:
model = models.Child model = models.Child
fields = ("id", "first_name", "last_name", "birth_date", "slug", "picture") fields = (
"id",
"first_name",
"last_name",
"birth_date",
"birth_time",
"slug",
"picture",
)
lookup_field = "slug" lookup_field = "slug"

View File

@ -139,13 +139,19 @@ class ChildAPITestCase(TestBase.BabyBuddyAPITestCaseBase):
"first_name": "Fake", "first_name": "Fake",
"last_name": "Child", "last_name": "Child",
"birth_date": "2017-11-11", "birth_date": "2017-11-11",
"birth_time": None,
"slug": "fake-child", "slug": "fake-child",
"picture": None, "picture": None,
}, },
) )
def test_post(self): def test_post(self):
data = {"first_name": "Test", "last_name": "Child", "birth_date": "2017-11-12"} data = {
"first_name": "Test",
"last_name": "Child",
"birth_date": "2017-11-12",
"birth_time": "23:25",
}
response = self.client.post(self.endpoint, data, format="json") response = self.client.post(self.endpoint, data, format="json")
self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual(response.status_code, status.HTTP_201_CREATED)
obj = models.Child.objects.get(pk=response.data["id"]) obj = models.Child.objects.get(pk=response.data["id"])

View File

@ -33,9 +33,16 @@ class ChildViewSet(viewsets.ModelViewSet):
queryset = models.Child.objects.all() queryset = models.Child.objects.all()
serializer_class = serializers.ChildSerializer serializer_class = serializers.ChildSerializer
lookup_field = "slug" lookup_field = "slug"
filterset_fields = ("id", "first_name", "last_name", "slug", "birth_date") filterset_fields = (
ordering_fields = ("birth_date", "first_name", "last_name", "slug") "id",
ordering = "-birth_date" "first_name",
"last_name",
"slug",
"birth_date",
"birth_time",
)
ordering_fields = ("birth_date", "birth_time", "first_name", "last_name", "slug")
ordering = ["-birth_date", "-birth_time"]
class DiaperChangeViewSet(viewsets.ModelViewSet): class DiaperChangeViewSet(viewsets.ModelViewSet):

View File

@ -49,10 +49,10 @@ class ChildImportExportResource(resources.ModelResource):
@admin.register(models.Child) @admin.register(models.Child)
class ChildAdmin(ImportExportMixin, ExportActionMixin, admin.ModelAdmin): class ChildAdmin(ImportExportMixin, ExportActionMixin, admin.ModelAdmin):
list_display = ("first_name", "last_name", "birth_date", "slug") list_display = ("first_name", "last_name", "birth_date", "birth_time", "slug")
list_filter = ("last_name",) list_filter = ("last_name",)
search_fields = ("first_name", "last_name", "birth_date") search_fields = ("first_name", "last_name", "birth_date")
fields = ["first_name", "last_name", "birth_date"] fields = ["first_name", "last_name", "birth_date", "birth_time"]
if settings.BABY_BUDDY["ALLOW_UPLOADS"]: if settings.BABY_BUDDY["ALLOW_UPLOADS"]:
fields.append("picture") fields.append("picture")
resource_class = ChildImportExportResource resource_class = ChildImportExportResource

View File

@ -7,7 +7,7 @@ from django.utils.translation import gettext_lazy as _
from taggit.forms import TagField from taggit.forms import TagField
from babybuddy.widgets import DateInput, DateTimeInput from babybuddy.widgets import DateInput, DateTimeInput, TimeInput
from core import models from core import models
from core.widgets import TagsEditor, ChildRadioSelect from core.widgets import TagsEditor, ChildRadioSelect
@ -107,11 +107,12 @@ class CoreModelForm(forms.ModelForm):
class ChildForm(forms.ModelForm): class ChildForm(forms.ModelForm):
class Meta: class Meta:
model = models.Child model = models.Child
fields = ["first_name", "last_name", "birth_date"] fields = ["first_name", "last_name", "birth_date", "birth_time"]
if settings.BABY_BUDDY["ALLOW_UPLOADS"]: if settings.BABY_BUDDY["ALLOW_UPLOADS"]:
fields.append("picture") fields.append("picture")
widgets = { widgets = {
"birth_date": DateInput(), "birth_date": DateInput(),
"birth_time": TimeInput(),
} }

View File

@ -0,0 +1,17 @@
# Generated by Django 4.2.6 on 2023-10-21 17:45
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("core", "0031_note_image"),
]
operations = [
migrations.AddField(
model_name="child",
name="birth_time",
field=models.TimeField(blank=True, null=True, verbose_name="Birth time"),
),
]

View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import datetime
import re import re
from datetime import timedelta from datetime import timedelta
@ -165,6 +166,7 @@ class Child(models.Model):
blank=True, max_length=255, verbose_name=_("Last name") blank=True, max_length=255, verbose_name=_("Last name")
) )
birth_date = models.DateField(blank=False, null=False, verbose_name=_("Birth date")) birth_date = models.DateField(blank=False, null=False, verbose_name=_("Birth date"))
birth_time = models.TimeField(blank=True, null=True, verbose_name=_("Birth time"))
slug = models.SlugField( slug = models.SlugField(
allow_unicode=True, allow_unicode=True,
blank=False, blank=False,
@ -206,6 +208,13 @@ class Child(models.Model):
return "{}, {}".format(self.last_name, self.first_name) return "{}, {}".format(self.last_name, self.first_name)
return "{} {}".format(self.first_name, self.last_name) return "{} {}".format(self.first_name, self.last_name)
def birth_datetime(self):
if self.birth_time:
return timezone.make_aware(
datetime.datetime.combine(self.birth_date, self.birth_time)
)
return self.birth_date
@classmethod @classmethod
def count(cls): def count(cls):
"""Get a (cached) count of total number of Child instances.""" """Get a (cached) count of total number of Child instances."""

View File

@ -22,8 +22,8 @@
{% endif %} {% endif %}
<div class="child-name display-4">{{ object }}</div> <div class="child-name display-4">{{ object }}</div>
<p class="lead"> <p class="lead">
{% trans "Born" %} <span class="text-secondary">{{ object.birth_date }}</span><br/> {% trans "Born" %} <span class="text-secondary">{{ object.birth_datetime }}</span><br/>
{% trans "Age" %} <span class="text-secondary">{{ object.birth_date|child_age_string }}</span> {% trans "Age" %} <span class="text-secondary">{{ object.birth_datetime|child_age_string }}</span>
</p> </p>
{% include 'dashboard/child_button_group.html' %} {% include 'dashboard/child_button_group.html' %}
</div> </div>

View File

@ -42,7 +42,7 @@
<a href="{% url 'core:child' child.slug %}">{{ child.first_name }}</a> <a href="{% url 'core:child' child.slug %}">{{ child.first_name }}</a>
</th> </th>
<td>{{ child.last_name }}</td> <td>{{ child.last_name }}</td>
<td>{{ child.birth_date }}</td> <td>{{ child.birth_datetime }}</td>
<td class="text-center"> <td class="text-center">
<div class="btn-group btn-group-sm" role="group" aria-label="{% trans "Actions" %}"> <div class="btn-group btn-group-sm" role="group" aria-label="{% trans "Actions" %}">

View File

@ -20,9 +20,6 @@ def child_age_string(birth_date):
""" """
if not birth_date: if not birth_date:
return "" return ""
# Return "0 days" for anything under one day.
elif timezone.localdate() - birth_date < timezone.timedelta(days=1):
return _("0 days")
try: try:
return timesince.timesince(birth_date, depth=1) return timesince.timesince(birth_date, depth=1)
except (ValueError, TypeError): except (ValueError, TypeError):

View File

@ -1,2 +1,2 @@
first_name,last_name,birth_date first_name,last_name,birth_date,birth_time
Emily,Huerta,2020-01-17 Emily,Huerta,2020-01-17,10:21

1 first_name last_name birth_date birth_time
2 Emily Huerta 2020-01-17 10:21

View File

@ -24,8 +24,8 @@ class TemplateTagsTestCase(TestCase):
) )
def test_child_age_string(self): def test_child_age_string(self):
date = timezone.localdate() - timezone.timedelta(days=0, hours=6) date = timezone.localtime() - timezone.timedelta(days=0, hours=6)
self.assertEqual("0 days", duration.child_age_string(date)) self.assertEqual("6\xa0hours", duration.child_age_string(date))
date = timezone.localdate() - timezone.timedelta(days=1, hours=6) date = timezone.localdate() - timezone.timedelta(days=1, hours=6)
self.assertEqual("1\xa0day", duration.child_age_string(date)) self.assertEqual("1\xa0day", duration.child_age_string(date))
date = timezone.localdate() - timezone.timedelta(days=45) date = timezone.localdate() - timezone.timedelta(days=45)

File diff suppressed because it is too large Load Diff