513: Make nap user toggleable (#641)

* Add `nap` field, remove `napping` field.

* Default `nap` property to NULL

* Update existing tests

* Format the code!!

* Allow `Sleep.nap` to be blank

* Migrate settings from `NAP_START_MIN` AND `NAP_START_MAX`

* Remove `active` class from boolean fields

* Correct test method name and user config

* Add forms test

* Use settings for Sleep nap model tests
This commit is contained in:
Christopher Charbonneau Wells 2023-05-07 15:10:50 -07:00 committed by GitHub
parent a669decc88
commit 31a0aa4741
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 256 additions and 110 deletions

View File

@ -527,15 +527,15 @@ class SleepAPITestCase(TestBase.BabyBuddyAPITestCaseBase):
def test_get(self):
response = self.client.get(self.endpoint)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(
self.assertDictEqual(
response.data["results"][0],
{
"id": 4,
"child": 1,
"start": "2017-11-18T19:00:00-05:00",
"end": "2017-11-18T23:00:00-05:00",
"duration": "04:00:00",
"nap": False,
"start": "2017-11-19T03:00:00-05:00",
"end": "2017-11-19T04:30:00-05:00",
"duration": "01:30:00",
"nap": True,
"notes": "lots of squirming",
"tags": [],
},
@ -558,7 +558,7 @@ class SleepAPITestCase(TestBase.BabyBuddyAPITestCaseBase):
endpoint = "{}{}/".format(self.endpoint, 4)
response = self.client.get(endpoint)
entry = response.data
entry["end"] = "2017-11-18T23:30:00-05:00"
entry["end"] = "2017-11-19T08:30:00-05:00"
response = self.client.patch(
endpoint,
{

View File

@ -1,10 +1,13 @@
# -*- coding: utf-8 -*-
import datetime
import os
from django.apps import AppConfig
from django.conf import settings
from django.db.models.signals import post_migrate
from dbsettings.loading import set_setting_value, setting_in_db
from babybuddy import VERSION
@ -14,6 +17,39 @@ def create_read_only_group(sender, **kwargs):
Group.objects.get_or_create(name=settings.BABY_BUDDY["READ_ONLY_GROUP_NAME"])
def set_default_site_settings(sender, **kwargs):
"""
Sets default values for site-wide settings.
Based on `dbsettings.utils.set_defaults` which no longer seem to work in
the latest versions of Django.
"""
from core import models
# Removed `NAP_START_MIN` and `NAP_START_MAX` values are referenced here
# for pre-2.0.0 migrations.
try:
nap_start_min = datetime.datetime.strptime(
os.environ.get("NAP_START_MIN"), "%H:%M"
).time()
except (TypeError, ValueError):
nap_start_min = models.Sleep.settings.nap_start_min
try:
nap_start_max = datetime.datetime.strptime(
os.environ.get("NAP_START_MAX"), "%H:%M"
).time()
except (TypeError, ValueError):
nap_start_max = models.Sleep.settings.nap_start_max
defaults = (
("Sleep", "nap_start_min", nap_start_min),
("Sleep", "nap_start_max", nap_start_max),
)
for class_name, attribute_name, value in defaults:
if not setting_in_db("core.models", class_name, attribute_name):
set_setting_value("core.models", class_name, attribute_name, value)
class BabyBuddyConfig(AppConfig):
name = "babybuddy"
verbose_name = "Baby Buddy"
@ -25,3 +61,4 @@ class BabyBuddyConfig(AppConfig):
commit = open(".git/refs/heads/master").read()
self.version_string += " ({})".format(commit[0:7])
post_migrate.connect(create_read_only_group, sender=self)
post_migrate.connect(set_default_site_settings, sender=self)

View File

@ -332,10 +332,10 @@
"fields":
{
"child": 1,
"start": "2017-11-18T04:30:00Z",
"start": "2017-11-17T20:30:00Z",
"end": "2017-11-18T05:30:00Z",
"duration": "01:00:00",
"napping": false
"duration": "09:00:00",
"nap": false
}
},
{
@ -347,7 +347,7 @@
"start": "2017-11-18T15:00:00Z",
"end": "2017-11-18T17:00:00Z",
"duration": "02:00:00",
"napping": true
"nap": true
}
},
{
@ -357,9 +357,9 @@
{
"child": 1,
"start": "2017-11-18T19:00:00Z",
"end": "2017-11-18T19:30:00Z",
"duration": "00:30:00",
"napping": false
"end": "2017-11-19T04:30:00Z",
"duration": "09:30:00",
"nap": false
}
},
{
@ -368,11 +368,11 @@
"fields":
{
"child": 1,
"start": "2017-11-19T00:00:00Z",
"end": "2017-11-19T04:00:00Z",
"duration": "04:00:00",
"start": "2017-11-19T08:00:00Z",
"end": "2017-11-19T09:30:00Z",
"duration": "01:30:00",
"notes": "lots of squirming",
"napping": false
"nap": true
}
},
{

View File

@ -8,6 +8,8 @@ from django.core.management import call_command
from django.core.management.base import BaseCommand, CommandError
from django.core.management.commands.flush import Command as Flush
from dbsettings.models import Setting
from .fake import Command as Fake
from .migrate import Command as Migrate
@ -38,6 +40,9 @@ class Command(BaseCommand):
if verbosity > 0:
self.stdout.write(self.style.SUCCESS("Database flushed."))
# Remove all site-wide settings.
Setting.objects.all().delete()
# Run migrations for all Baby Buddy apps.
for config in apps.app_configs.values():
if path.split(path.split(config.path)[0])[1] == "babybuddy":

View File

@ -19,3 +19,8 @@ EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
# See https://django-axes.readthedocs.io/en/latest/4_configuration.html
AXES_ENABLED = False
# DBSettings configuration
# See https://github.com/zlorf/django-dbsettings#a-note-about-caching
DBSETTINGS_USE_CACHE = False

View File

@ -11,7 +11,7 @@
{% else %}
{{ field|add_class:"btn-check" }}
{% endif %}
<label for="id_{{ field.name }}" class="btn btn-outline-light btn-no-hover{% if field.value %} active{% endif %}">
<label for="id_{{ field.name }}" class="btn btn-outline-light btn-no-hover">
{{ field.label }}
</label>
{% elif 'choice' in field|field_type %}

View File

@ -27,7 +27,7 @@ class SiteSettingsTestCase(TestCase):
is_superuser=True, is_staff=True, **cls.credentials
)
def test_default_settings(self):
def test_settings_default(self):
self.c.login(**self.credentials)
page = self.c.get("/settings/")
self.assertEqual(page.status_code, 200)
@ -40,9 +40,8 @@ class SiteSettingsTestCase(TestCase):
"06:00:00",
)
def test_nap_start_settings(self):
def test_settings_nap_start(self):
self.c.login(**self.credentials)
self.assert_naps()
params = {
"core.models__Sleep__nap_start_max": "20:00:00",
"core.models__Sleep__nap_start_min": "09:00:00",
@ -57,17 +56,3 @@ class SiteSettingsTestCase(TestCase):
Sleep.settings.nap_start_min.strftime("%H:%M:%S"),
params["core.models__Sleep__nap_start_min"],
)
self.assert_naps()
def assert_naps(self):
"""
Asserts sleep instances filtered with nap start min and max match nap instances.
"""
instances = Sleep.objects.filter(
start__time__range=(
Sleep.settings.nap_start_min.strftime("%H:%M:%S"),
Sleep.settings.nap_start_max.strftime("%H:%M:%S"),
)
)
naps = Sleep.naps.all()
self.assertQuerySetEqual(instances, naps)

View File

@ -21,9 +21,9 @@ class TemplateTagsTestCase(TestCase):
)
self.assertEqual(babybuddy.get_child_count(), 2)
def user_is_read_only(self):
def test_user_is_read_only(self):
user = get_user_model().objects.create_user(
username="readonly", password="readonly", is_superuser=False, is_staf=False
username="readonly", password="readonly", is_superuser=False, is_staff=False
)
self.assertFalse(babybuddy.user_is_read_only(user))

View File

@ -62,7 +62,20 @@ def set_initial_values(kwargs, form_type):
last_feed_args["method"] = last_method
kwargs["initial"].update(last_feed_args)
# Remove custom kwargs so they do not interfere with `super` calls.
# Set default "nap" value for Sleep instances.
if form_type == SleepForm and "nap" not in kwargs["initial"]:
try:
start = timezone.localtime(kwargs["initial"]["start"]).time()
except KeyError:
start = timezone.localtime().time()
nap = (
models.Sleep.settings.nap_start_min
<= start
<= models.Sleep.settings.nap_start_max
)
kwargs["initial"].update({"nap": nap})
# Remove custom kwargs, so they do not interfere with `super` calls.
for key in ["child", "timer"]:
try:
kwargs.pop(key)
@ -181,7 +194,7 @@ class NoteForm(CoreModelForm, TaggableModelForm):
class SleepForm(CoreModelForm, TaggableModelForm):
class Meta:
model = models.Sleep
fields = ["child", "start", "end", "notes", "tags"]
fields = ["child", "start", "end", "nap", "notes", "tags"]
widgets = {
"child": ChildRadioSelect,
"start": DateTimeInput(),

View File

@ -20,7 +20,8 @@ class Migration(migrations.Migration):
name="napping",
field=models.BooleanField(null=True, verbose_name="Napping"),
),
migrations.RunPython(set_napping, reverse_code=migrations.RunPython.noop),
# Migration superseded by 0028_alter_sleep_options_remove_sleep_napping_sleep_nap.py
# migrations.RunPython(set_napping, reverse_code=migrations.RunPython.noop),
migrations.AlterField(
model_name="sleep",
name="napping",

View File

@ -0,0 +1,53 @@
# Generated by Django 4.2 on 2023-05-07 00:28
from django.db import migrations, models
from django.utils import timezone
def set_sleep_nap_values(apps, schema_editor):
# The model must be imported to ensure its overridden `save` method is run.
from core.models import Sleep
for sleep in Sleep.objects.all():
sleep.nap = (
Sleep.settings.nap_start_min
<= timezone.localtime(sleep.start).time()
<= Sleep.settings.nap_start_max
)
sleep.save()
class Migration(migrations.Migration):
dependencies = [
("core", "0027_alter_timer_options_remove_timer_duration_and_more"),
]
operations = [
migrations.AlterModelOptions(
name="sleep",
options={
"default_permissions": ("view", "add", "change", "delete"),
"ordering": ["-start"],
"permissions": [("can_edit_sleep_settings", "Can edit Sleep settings")],
"verbose_name": "Sleep",
"verbose_name_plural": "Sleep",
},
),
migrations.RemoveField(
model_name="sleep",
name="napping",
),
migrations.AddField(
model_name="sleep",
name="nap",
field=models.BooleanField(null=True, verbose_name="Nap"),
),
migrations.RunPython(
set_sleep_nap_values, reverse_code=migrations.RunPython.noop
),
migrations.AlterField(
model_name="sleep",
name="nap",
field=models.BooleanField(blank=True, verbose_name="Nap"),
),
]

View File

@ -418,12 +418,6 @@ class Note(models.Model):
return str(_("Note"))
class NapsManager(models.Manager):
def get_queryset(self):
qs = super(NapsManager, self).get_queryset()
return qs.filter(id__in=[obj.id for obj in qs if obj.nap])
class Pumping(models.Model):
model_name = "pumping"
child = models.ForeignKey(
@ -459,7 +453,6 @@ class Sleep(models.Model):
child = models.ForeignKey(
"Child", on_delete=models.CASCADE, related_name="sleep", verbose_name=_("Child")
)
napping = models.BooleanField(editable=False, null=True, verbose_name=_("Napping"))
start = models.DateTimeField(
blank=False,
default=timezone.localtime,
@ -469,6 +462,7 @@ class Sleep(models.Model):
end = models.DateTimeField(
blank=False, default=timezone.localtime, null=False, verbose_name=_("End time")
)
nap = models.BooleanField(null=False, blank=True, verbose_name=_("Nap"))
duration = models.DurationField(
editable=False, null=True, verbose_name=_("Duration")
)
@ -476,7 +470,6 @@ class Sleep(models.Model):
tags = TaggableManager(blank=True, through=Tagged)
objects = models.Manager()
naps = NapsManager()
settings = NapSettings(_("Nap settings"))
class Meta:
@ -488,19 +481,15 @@ class Sleep(models.Model):
def __str__(self):
return str(_("Sleep"))
@property
def nap(self):
local_start_time = timezone.localtime(self.start).time()
return (
def save(self, *args, **kwargs):
if self.nap is None:
self.nap = (
Sleep.settings.nap_start_min
<= local_start_time
<= timezone.localtime(self.start).time()
<= Sleep.settings.nap_start_max
)
def save(self, *args, **kwargs):
if self.start and self.end:
self.duration = self.end - self.start
self.napping = self.nap
super(Sleep, self).save(*args, **kwargs)
def clean(self):

View File

@ -1,40 +1,40 @@
child_id,start,end,notes
1,2020-02-17 00:14:09,2020-02-17 02:48:09,
1,2020-02-16 19:37:16,2020-02-16 22:43:16,
1,2020-02-16 17:19:16,2020-02-16 19:00:16,
1,2020-02-16 14:42:52,2020-02-16 16:35:52,
1,2020-02-16 11:28:41,2020-02-16 13:21:41,
1,2020-02-16 07:38:01,2020-02-16 08:55:01,
1,2020-02-16 03:12:01,2020-02-16 06:17:01,
1,2020-02-15 22:53:01,2020-02-16 01:21:01,Experience charge from woman fight. Court direction watch particular. Society price air difference chance consider find. Include word office story official statement life. Street kid develop enough need necessary.
1,2020-02-15 17:37:21,2020-02-15 19:04:21,
1,2020-02-15 14:32:21,2020-02-15 16:02:21,
1,2020-02-15 11:38:21,2020-02-15 13:10:21,
1,2020-02-15 07:51:45,2020-02-15 08:25:45,
1,2020-02-15 03:06:24,2020-02-15 05:41:24,
1,2020-02-14 21:58:58,2020-02-15 01:02:58,
1,2020-02-14 18:41:28,2020-02-14 19:23:28,Chance rate see consider still according. Technology series key recognize. Rise avoid growth weight.
1,2020-02-14 15:29:28,2020-02-14 16:57:28,Million tough many debate price. Tend south my home training free actually same. Mr imagine international.
1,2020-02-14 12:12:28,2020-02-14 13:51:28,
1,2020-02-14 07:41:40,2020-02-14 09:30:40,Mrs politics risk million education reach spring.
1,2020-02-14 02:18:07,2020-02-14 05:29:07,
1,2020-02-13 21:06:46,2020-02-13 23:40:46,
1,2020-02-13 18:05:46,2020-02-13 19:40:46,
1,2020-02-13 14:15:54,2020-02-13 15:40:54,
1,2020-02-13 09:39:03,2020-02-13 11:38:03,
1,2020-02-13 04:00:42,2020-02-13 08:03:42,
1,2020-02-12 22:15:50,2020-02-13 01:46:50,
1,2020-02-12 18:17:05,2020-02-12 19:35:05,
1,2020-02-12 15:23:05,2020-02-12 16:43:05,
1,2020-02-12 05:54:01,2020-02-12 11:48:01,Edge fact officer any.
1,2020-02-11 21:00:14,2020-02-12 01:58:14,
1,2020-02-11 17:33:04,2020-02-11 19:21:04,
1,2020-02-11 14:51:04,2020-02-11 15:46:04,
1,2020-02-11 12:49:10,2020-02-11 13:20:10,
1,2020-02-11 08:30:34,2020-02-11 09:17:34,
1,2020-02-11 06:35:34,2020-02-11 07:10:34,
1,2020-02-10 23:56:34,2020-02-11 05:00:34,Image last next important. Style oil season talk family television.
1,2020-02-10 18:39:49,2020-02-10 20:39:49,
1,2020-02-10 14:44:33,2020-02-10 16:31:33,
1,2020-02-10 10:25:06,2020-02-10 11:37:06,Other area cover military. Personal art decade guy. Traditional majority time term on life north. Leg drop most message within believe.
1,2020-02-10 05:36:55,2020-02-10 07:48:55,
child_id,start,nap,end,notes
1,2020-02-17 00:14:09,0,2020-02-17 02:48:09,
1,2020-02-16 19:37:16,0,2020-02-16 22:43:16,
1,2020-02-16 17:19:16,1,2020-02-16 19:00:16,
1,2020-02-16 14:42:52,1,2020-02-16 16:35:52,
1,2020-02-16 11:28:41,1,2020-02-16 13:21:41,
1,2020-02-16 07:38:01,1,2020-02-16 08:55:01,
1,2020-02-16 03:12:01,0,2020-02-16 06:17:01,
1,2020-02-15 22:53:01,0,2020-02-16 01:21:01,Experience charge from woman fight. Court direction watch particular. Society price air difference chance consider find. Include word office story official statement life. Street kid develop enough need necessary.
1,2020-02-15 17:37:21,1,2020-02-15 19:04:21,
1,2020-02-15 14:32:21,1,2020-02-15 16:02:21,
1,2020-02-15 11:38:21,1,2020-02-15 13:10:21,
1,2020-02-15 07:51:45,1,2020-02-15 08:25:45,
1,2020-02-15 03:06:24,0,2020-02-15 05:41:24,
1,2020-02-14 21:58:58,0,2020-02-15 01:02:58,
1,2020-02-14 18:41:28,1,2020-02-14 19:23:28,Chance rate see consider still according. Technology series key recognize. Rise avoid growth weight.
1,2020-02-14 15:29:28,1,2020-02-14 16:57:28,Million tough many debate price. Tend south my home training free actually same. Mr imagine international.
1,2020-02-14 12:12:28,1,2020-02-14 13:51:28,
1,2020-02-14 07:41:40,1,2020-02-14 09:30:40,Mrs politics risk million education reach spring.
1,2020-02-14 02:18:07,0,2020-02-14 05:29:07,
1,2020-02-13 21:06:46,0,2020-02-13 23:40:46,
1,2020-02-13 18:05:46,0,2020-02-13 19:40:46,
1,2020-02-13 14:15:54,1,2020-02-13 15:40:54,
1,2020-02-13 09:39:03,1,2020-02-13 11:38:03,
1,2020-02-13 04:00:42,0,2020-02-13 08:03:42,
1,2020-02-12 22:15:50,0,2020-02-13 01:46:50,
1,2020-02-12 18:17:05,1,2020-02-12 19:35:05,
1,2020-02-12 15:23:05,1,2020-02-12 16:43:05,
1,2020-02-12 05:54:01,0,2020-02-12 11:48:01,Edge fact officer any.
1,2020-02-11 21:00:14,0,2020-02-12 01:58:14,
1,2020-02-11 17:33:04,1,2020-02-11 19:21:04,
1,2020-02-11 14:51:04,1,2020-02-11 15:46:04,
1,2020-02-11 12:49:10,1,2020-02-11 13:20:10,
1,2020-02-11 08:30:34,1,2020-02-11 09:17:34,
1,2020-02-11 06:35:34,0,2020-02-11 07:10:34,
1,2020-02-10 23:56:34,0,2020-02-11 05:00:34,Image last next important. Style oil season talk family television.
1,2020-02-10 18:39:49,1,2020-02-10 20:39:49,
1,2020-02-10 14:44:33,1,2020-02-10 16:31:33,
1,2020-02-10 10:25:06,1,2020-02-10 11:37:06,Other area cover military. Personal art decade guy. Traditional majority time term on life north. Leg drop most message within believe.
1,2020-02-10 05:36:55,0,2020-02-10 07:48:55,

1 child_id start nap end notes
2 1 2020-02-17 00:14:09 0 2020-02-17 02:48:09
3 1 2020-02-16 19:37:16 0 2020-02-16 22:43:16
4 1 2020-02-16 17:19:16 1 2020-02-16 19:00:16
5 1 2020-02-16 14:42:52 1 2020-02-16 16:35:52
6 1 2020-02-16 11:28:41 1 2020-02-16 13:21:41
7 1 2020-02-16 07:38:01 1 2020-02-16 08:55:01
8 1 2020-02-16 03:12:01 0 2020-02-16 06:17:01
9 1 2020-02-15 22:53:01 0 2020-02-16 01:21:01 Experience charge from woman fight. Court direction watch particular. Society price air difference chance consider find. Include word office story official statement life. Street kid develop enough need necessary.
10 1 2020-02-15 17:37:21 1 2020-02-15 19:04:21
11 1 2020-02-15 14:32:21 1 2020-02-15 16:02:21
12 1 2020-02-15 11:38:21 1 2020-02-15 13:10:21
13 1 2020-02-15 07:51:45 1 2020-02-15 08:25:45
14 1 2020-02-15 03:06:24 0 2020-02-15 05:41:24
15 1 2020-02-14 21:58:58 0 2020-02-15 01:02:58
16 1 2020-02-14 18:41:28 1 2020-02-14 19:23:28 Chance rate see consider still according. Technology series key recognize. Rise avoid growth weight.
17 1 2020-02-14 15:29:28 1 2020-02-14 16:57:28 Million tough many debate price. Tend south my home training free actually same. Mr imagine international.
18 1 2020-02-14 12:12:28 1 2020-02-14 13:51:28
19 1 2020-02-14 07:41:40 1 2020-02-14 09:30:40 Mrs politics risk million education reach spring.
20 1 2020-02-14 02:18:07 0 2020-02-14 05:29:07
21 1 2020-02-13 21:06:46 0 2020-02-13 23:40:46
22 1 2020-02-13 18:05:46 0 2020-02-13 19:40:46
23 1 2020-02-13 14:15:54 1 2020-02-13 15:40:54
24 1 2020-02-13 09:39:03 1 2020-02-13 11:38:03
25 1 2020-02-13 04:00:42 0 2020-02-13 08:03:42
26 1 2020-02-12 22:15:50 0 2020-02-13 01:46:50
27 1 2020-02-12 18:17:05 1 2020-02-12 19:35:05
28 1 2020-02-12 15:23:05 1 2020-02-12 16:43:05
29 1 2020-02-12 05:54:01 0 2020-02-12 11:48:01 Edge fact officer any.
30 1 2020-02-11 21:00:14 0 2020-02-12 01:58:14
31 1 2020-02-11 17:33:04 1 2020-02-11 19:21:04
32 1 2020-02-11 14:51:04 1 2020-02-11 15:46:04
33 1 2020-02-11 12:49:10 1 2020-02-11 13:20:10
34 1 2020-02-11 08:30:34 1 2020-02-11 09:17:34
35 1 2020-02-11 06:35:34 0 2020-02-11 07:10:34
36 1 2020-02-10 23:56:34 0 2020-02-11 05:00:34 Image last next important. Style oil season talk family television.
37 1 2020-02-10 18:39:49 1 2020-02-10 20:39:49
38 1 2020-02-10 14:44:33 1 2020-02-10 16:31:33
39 1 2020-02-10 10:25:06 1 2020-02-10 11:37:06 Other area cover military. Personal art decade guy. Traditional majority time term on life north. Leg drop most message within believe.
40 1 2020-02-10 05:36:55 0 2020-02-10 07:48:55

View File

@ -545,6 +545,26 @@ class SleepFormsTestCase(FormsTestCaseBase):
self.assertEqual(page.status_code, 200)
self.assertContains(page, "Sleep entry deleted")
def test_nap_default(self):
models.Sleep.settings.nap_start_min = (
timezone.now() - timezone.timedelta(hours=1)
).time()
models.Sleep.settings.nap_start_max = (
timezone.now() + timezone.timedelta(hours=1)
).time()
response = self.c.get("/sleep/add/")
self.assertTrue(response.context["form"].initial["nap"])
def test_not_nap_default(self):
models.Sleep.settings.nap_start_min = (
timezone.now() + timezone.timedelta(hours=1)
).time()
models.Sleep.settings.nap_start_max = (
timezone.now() + timezone.timedelta(hours=2)
).time()
response = self.c.get("/sleep/add/")
self.assertFalse(response.context["form"].initial["nap"])
class TaggedFormsTestCase(FormsTestCaseBase):
@classmethod

View File

@ -1,4 +1,6 @@
# -*- coding: utf-8 -*-
from datetime import datetime
from django.contrib.auth import get_user_model
from django.core.management import call_command
from django.test import TestCase
@ -210,6 +212,42 @@ class SleepTestCase(TestCase):
self.assertEqual(str(sleep), "Sleep")
self.assertEqual(sleep.duration, sleep.end - sleep.start)
def test_sleep_nap(self):
models.Sleep.settings.nap_start_min = (
timezone.now() - timezone.timedelta(hours=1)
).time()
models.Sleep.settings.nap_start_max = (
timezone.now() + timezone.timedelta(hours=1)
).time()
sleep = models.Sleep.objects.create(
child=self.child,
start=timezone.now(),
end=(timezone.now() + timezone.timedelta(hours=2)),
)
self.assertTrue(sleep.nap)
def test_sleep_not_nap(self):
models.Sleep.settings.nap_start_min = (
timezone.now() + timezone.timedelta(hours=1)
).time()
models.Sleep.settings.nap_start_max = (
timezone.now() + timezone.timedelta(hours=2)
).time()
sleep = models.Sleep.objects.create(
child=self.child,
start=timezone.now(),
end=(timezone.now() + timezone.timedelta(hours=8)),
)
self.assertFalse(sleep.nap)
sleep = models.Sleep.objects.create(
child=self.child,
start=timezone.now(),
end=(timezone.now() + timezone.timedelta(hours=8)),
nap=True,
)
self.assertTrue(sleep.nap)
class TagTestCase(TestCase):
def setUp(self):

View File

@ -324,9 +324,9 @@ def card_sleep_naps_day(context, child, date=None):
"""
if not date:
date = timezone.localtime().date()
instances = models.Sleep.naps.filter(child=child).filter(
instances = models.Sleep.objects.filter(child=child, nap=True).filter(
start__year=date.year, start__month=date.month, start__day=date.day
) | models.Sleep.naps.filter(child=child).filter(
) | models.Sleep.objects.filter(child=child, nap=True).filter(
end__year=date.year, end__month=date.month, end__day=date.day
)
empty = len(instances) == 0
@ -548,7 +548,7 @@ def _nap_statistics(child):
:param child: an instance of the Child model.
:returns: a dictionary of statistics.
"""
instances = models.Sleep.naps.filter(child=child).order_by("start")
instances = models.Sleep.objects.filter(child=child, nap=True).order_by("start")
if len(instances) == 0:
return False
naps = {

View File

@ -216,10 +216,10 @@ class TemplateTagsTestCase(TestCase):
self.assertEqual(data["type"], "sleep")
self.assertFalse(data["empty"])
self.assertFalse(data["hide_empty"])
self.assertEqual(data["sleeps"][0]["total"], timezone.timedelta(hours=7))
self.assertEqual(data["sleeps"][0]["count"], 4)
self.assertEqual(data["sleeps"][0]["total"], timezone.timedelta(seconds=43200))
self.assertEqual(data["sleeps"][0]["count"], 3)
self.assertEqual(data["sleeps"][1]["total"], timezone.timedelta(minutes=30))
self.assertEqual(data["sleeps"][1]["total"], timezone.timedelta(seconds=30600))
self.assertEqual(data["sleeps"][1]["count"], 1)
def test_card_sleep_naps_day(self):
@ -227,8 +227,8 @@ class TemplateTagsTestCase(TestCase):
self.assertEqual(data["type"], "sleep")
self.assertFalse(data["empty"])
self.assertFalse(data["hide_empty"])
self.assertEqual(data["total"], timezone.timedelta(0, 9000))
self.assertEqual(data["count"], 2)
self.assertEqual(data["total"], timezone.timedelta(0, 7200))
self.assertEqual(data["count"], 1)
def test_card_statistics(self):
data = cards.card_statistics(self.context, self.child)
@ -271,18 +271,18 @@ class TemplateTagsTestCase(TestCase):
},
{
"title": "Average nap duration",
"stat": timezone.timedelta(0, 4500),
"stat": timezone.timedelta(0, 6300),
"type": "duration",
},
{"title": "Average naps per day", "stat": 2.0, "type": "float"},
{"title": "Average naps per day", "stat": 1.0, "type": "float"},
{
"title": "Average sleep duration",
"stat": timezone.timedelta(0, 6750),
"stat": timezone.timedelta(0, 19800),
"type": "duration",
},
{
"title": "Average awake duration",
"stat": timezone.timedelta(0, 19200),
"stat": timezone.timedelta(0, 18000),
"type": "duration",
},
{"title": "Weight change per week", "stat": 1.0, "type": "float"},