mirror of https://github.com/snachodog/mybuddy.git
Finish up adding the brestpump measurement
This commit is contained in:
parent
3474185b00
commit
5c45b037f0
|
@ -63,6 +63,11 @@ class StartEndFieldFilter(ChildFieldFilter):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class BreastpumpFilter(TimeFieldFilter):
|
||||||
|
class Meta(TimeFieldFilter.Meta):
|
||||||
|
model = models.Breastpump
|
||||||
|
|
||||||
|
|
||||||
class DiaperChangeFilter(TimeFieldFilter, TagsFieldFilter):
|
class DiaperChangeFilter(TimeFieldFilter, TagsFieldFilter):
|
||||||
class Meta(TimeFieldFilter.Meta):
|
class Meta(TimeFieldFilter.Meta):
|
||||||
model = models.DiaperChange
|
model = models.DiaperChange
|
||||||
|
|
|
@ -102,6 +102,12 @@ class UserSerializer(serializers.ModelSerializer):
|
||||||
fields = ("id", "username")
|
fields = ("id", "username")
|
||||||
|
|
||||||
|
|
||||||
|
class BreastpumpSerializer(CoreModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = models.Breastpump
|
||||||
|
fields = ("id", "child", "amount", "time", "notes")
|
||||||
|
|
||||||
|
|
||||||
class ChildSerializer(serializers.HyperlinkedModelSerializer):
|
class ChildSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.Child
|
model = models.Child
|
||||||
|
|
|
@ -11,7 +11,7 @@ router.register(r"changes", views.DiaperChangeViewSet)
|
||||||
router.register(r"feedings", views.FeedingViewSet)
|
router.register(r"feedings", views.FeedingViewSet)
|
||||||
router.register(r"notes", views.NoteViewSet)
|
router.register(r"notes", views.NoteViewSet)
|
||||||
router.register(r"sleep", views.SleepViewSet)
|
router.register(r"sleep", views.SleepViewSet)
|
||||||
router.register(r"temperature", views.TemperatureViewSet)
|
router.register(r"breastpump", views.BreastpumpViewSet)
|
||||||
router.register(r"timers", views.TimerViewSet)
|
router.register(r"timers", views.TimerViewSet)
|
||||||
router.register(r"tummy-times", views.TummyTimeViewSet)
|
router.register(r"tummy-times", views.TummyTimeViewSet)
|
||||||
router.register(r"weight", views.WeightViewSet)
|
router.register(r"weight", views.WeightViewSet)
|
||||||
|
|
|
@ -16,6 +16,12 @@ class ChildViewSet(viewsets.ModelViewSet):
|
||||||
filterset_fields = ("first_name", "last_name", "slug", "birth_date")
|
filterset_fields = ("first_name", "last_name", "slug", "birth_date")
|
||||||
|
|
||||||
|
|
||||||
|
class BreastpumpViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = models.Breastpump.objects.all()
|
||||||
|
serializer_class = serializers.BreastpumpSerializer
|
||||||
|
filterset_class = filters.BreastpumpFilter
|
||||||
|
|
||||||
|
|
||||||
class DiaperChangeViewSet(viewsets.ModelViewSet):
|
class DiaperChangeViewSet(viewsets.ModelViewSet):
|
||||||
queryset = models.DiaperChange.objects.all()
|
queryset = models.DiaperChange.objects.all()
|
||||||
serializer_class = serializers.DiaperChangeSerializer
|
serializer_class = serializers.DiaperChangeSerializer
|
||||||
|
|
|
@ -20,6 +20,17 @@
|
||||||
"slug": "fake-child",
|
"slug": "fake-child",
|
||||||
"picture": ""
|
"picture": ""
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model": "core.breastpump",
|
||||||
|
"pk": 1,
|
||||||
|
"fields":
|
||||||
|
{
|
||||||
|
"child": 1,
|
||||||
|
"amount": 50.0,
|
||||||
|
"time": "2017-11-17T17:52:00Z",
|
||||||
|
"notes": "new device"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"model": "core.diaperchange",
|
"model": "core.diaperchange",
|
||||||
|
|
|
@ -75,6 +75,9 @@ class Command(BaseCommand):
|
||||||
"""
|
"""
|
||||||
self.time = self.child.birth_date
|
self.time = self.child.birth_date
|
||||||
|
|
||||||
|
self.breastpump = round(uniform(95.0, 102.0), 2)
|
||||||
|
self._add_breastpump_entry()
|
||||||
|
|
||||||
self.temperature = round(uniform(95.0, 102.0), 2)
|
self.temperature = round(uniform(95.0, 102.0), 2)
|
||||||
self._add_temperature_entry()
|
self._add_temperature_entry()
|
||||||
|
|
||||||
|
@ -103,6 +106,7 @@ class Command(BaseCommand):
|
||||||
self._add_diaperchange_entry()
|
self._add_diaperchange_entry()
|
||||||
self._add_feeding_entry()
|
self._add_feeding_entry()
|
||||||
self._add_diaperchange_entry()
|
self._add_diaperchange_entry()
|
||||||
|
self._add_breastpump_entry()
|
||||||
if choice([True, False]):
|
if choice([True, False]):
|
||||||
self._add_tummytime_entry()
|
self._add_tummytime_entry()
|
||||||
if choice([True, False]):
|
if choice([True, False]):
|
||||||
|
@ -110,6 +114,8 @@ class Command(BaseCommand):
|
||||||
self._add_tummytime_entry()
|
self._add_tummytime_entry()
|
||||||
if choice([True, False]):
|
if choice([True, False]):
|
||||||
self._add_temperature_entry()
|
self._add_temperature_entry()
|
||||||
|
if choice([True, False]):
|
||||||
|
self._add_breastpump_entry()
|
||||||
if (self.time - last_note_entry_time).days > 1 and choice([True, False]):
|
if (self.time - last_note_entry_time).days > 1 and choice([True, False]):
|
||||||
self._add_note_entry()
|
self._add_note_entry()
|
||||||
last_note_entry_time = self.time
|
last_note_entry_time = self.time
|
||||||
|
@ -126,6 +132,24 @@ class Command(BaseCommand):
|
||||||
self._add_bmi_entry()
|
self._add_bmi_entry()
|
||||||
last_bmi_entry_time = self.time
|
last_bmi_entry_time = self.time
|
||||||
|
|
||||||
|
|
||||||
|
@transaction.atomic
|
||||||
|
def _add_breastpump_entry(self):
|
||||||
|
"""
|
||||||
|
Add a Breastpump entry. This assumes a weekly interval.
|
||||||
|
:returns:
|
||||||
|
"""
|
||||||
|
self.amount = round(uniform(95.0, 102.0), 2)
|
||||||
|
|
||||||
|
notes = ""
|
||||||
|
if choice([True, False, False, False]):
|
||||||
|
notes = " ".join(self.faker.sentences(randint(1, 5)))
|
||||||
|
|
||||||
|
models.Breastpump.objects.create(
|
||||||
|
child=self.child, amount=self.amount, time=self.time, notes=notes
|
||||||
|
).save()
|
||||||
|
|
||||||
|
|
||||||
@transaction.atomic
|
@transaction.atomic
|
||||||
def _add_diaperchange_entry(self):
|
def _add_diaperchange_entry(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -87,6 +87,12 @@
|
||||||
{% trans "Weight" %}
|
{% trans "Weight" %}
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% if perms.core.add_breastpump %}
|
||||||
|
<a class="dropdown-item p-2" href="{% url 'core:breastpump-add' %}">
|
||||||
|
<i class="icon-breastpump" aria-hidden="true"></i>
|
||||||
|
{% trans "Breastpump" %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -235,6 +241,20 @@
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
{% if perms.core.view_breastpump %}
|
||||||
|
<a class="dropdown-item{% if request.path == '/breastpump/' %} active{% endif %}"
|
||||||
|
href="{% url 'core:breastpump-list' %}">
|
||||||
|
<i class="icon-breastpump" aria-hidden="true"></i>
|
||||||
|
{% trans "Breastpump" %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
{% if perms.core.add_breastpump %}
|
||||||
|
<a class="dropdown-item pl-5{% if request.path == '/breastpump/add/' %} active{% endif %}"
|
||||||
|
href="{% url 'core:breastpump-add' %}"><i class="icon-add" aria-hidden="true"></i>
|
||||||
|
{% trans "Breastpump entry" %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
|
@ -58,6 +58,27 @@ class ChildAdmin(ImportExportMixin, ExportActionMixin, admin.ModelAdmin):
|
||||||
resource_class = ChildImportExportResource
|
resource_class = ChildImportExportResource
|
||||||
|
|
||||||
|
|
||||||
|
class BreastpumpImportExportResource(ImportExportResourceBase):
|
||||||
|
class Meta:
|
||||||
|
model = models.Breastpump
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(models.Breastpump)
|
||||||
|
class BreastpumpAdmin(ImportExportMixin, ExportActionMixin, admin.ModelAdmin):
|
||||||
|
list_display = (
|
||||||
|
"child",
|
||||||
|
"amount",
|
||||||
|
"time",
|
||||||
|
)
|
||||||
|
list_filter = ("child",)
|
||||||
|
search_fields = (
|
||||||
|
"child__first_name",
|
||||||
|
"child__last_name",
|
||||||
|
"amount",
|
||||||
|
)
|
||||||
|
resource_class = BreastpumpImportExportResource
|
||||||
|
|
||||||
|
|
||||||
class DiaperChangeImportExportResource(ImportExportResourceBase):
|
class DiaperChangeImportExportResource(ImportExportResourceBase):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.DiaperChange
|
model = models.DiaperChange
|
||||||
|
|
|
@ -124,6 +124,21 @@ class ChildDeleteForm(forms.ModelForm):
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
|
||||||
|
class BreastpumpForm(CoreModelForm):
|
||||||
|
class Meta:
|
||||||
|
model = models.Breastpump
|
||||||
|
fields = ["child", "amount", "time", "notes"]
|
||||||
|
widgets = {
|
||||||
|
"time": forms.DateTimeInput(
|
||||||
|
attrs={
|
||||||
|
"autocomplete": "off",
|
||||||
|
"data-target": "#datetimepicker_time",
|
||||||
|
}
|
||||||
|
),
|
||||||
|
"notes": forms.Textarea(attrs={"rows": 5}),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class DiaperChangeForm(CoreModelForm):
|
class DiaperChangeForm(CoreModelForm):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = models.DiaperChange
|
model = models.DiaperChange
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
# Generated by Django 4.0.3 on 2022-03-02 23:17
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('core', '0018_bmi_headcircumference_height'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Breastpump",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.AutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("amount", models.FloatField(verbose_name="Amount")),
|
||||||
|
("time", models.DateTimeField(verbose_name="Time")),
|
||||||
|
(
|
||||||
|
"child",
|
||||||
|
models.ForeignKey(
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="breastpump",
|
||||||
|
to="core.Child",
|
||||||
|
verbose_name="Child",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "Breastpump",
|
||||||
|
"verbose_name_plural": "Breastpump",
|
||||||
|
"ordering": ["-time"],
|
||||||
|
"default_permissions": ("view", "add", "change", "delete"),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="breastpump",
|
||||||
|
name="notes",
|
||||||
|
field=models.TextField(blank=True, null=True, verbose_name="Notes"),
|
||||||
|
),
|
||||||
|
]
|
|
@ -173,6 +173,35 @@ class TaggableManager(TaggitTaggableManager):
|
||||||
return super().formfield(*args, **kwargs)
|
return super().formfield(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class Breastpump(models.Model):
|
||||||
|
model_name = "breastpump"
|
||||||
|
child = models.ForeignKey(
|
||||||
|
"Child",
|
||||||
|
on_delete=models.CASCADE,
|
||||||
|
related_name="breastpump",
|
||||||
|
verbose_name=_("Child"),
|
||||||
|
)
|
||||||
|
amount = models.FloatField(
|
||||||
|
blank=False, null=False, verbose_name=_("Amount")
|
||||||
|
)
|
||||||
|
time = models.DateTimeField(blank=False, null=False, verbose_name=_("Time"))
|
||||||
|
notes = models.TextField(blank=True, null=True, verbose_name=_("Notes"))
|
||||||
|
|
||||||
|
objects = models.Manager()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
default_permissions = ("view", "add", "change", "delete")
|
||||||
|
ordering = ["-time"]
|
||||||
|
verbose_name = _("Breastpump")
|
||||||
|
verbose_name_plural = _("Breastpump")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return str(_("Breastpump"))
|
||||||
|
|
||||||
|
def clean(self):
|
||||||
|
validate_time(self.time, "time")
|
||||||
|
|
||||||
|
|
||||||
class Child(models.Model):
|
class Child(models.Model):
|
||||||
model_name = "child"
|
model_name = "child"
|
||||||
first_name = models.CharField(max_length=255, verbose_name=_("First name"))
|
first_name = models.CharField(max_length=255, verbose_name=_("First name"))
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
{% extends 'babybuddy/page.html' %}
|
||||||
|
{% load i18n widget_tweaks %}
|
||||||
|
|
||||||
|
{% block title %}{% trans "Delete a Breastpump Reading" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block breadcrumbs %}
|
||||||
|
<li class="breadcrumb-item"><a href="{% url 'core:breastpump-list' %}">{% trans "Breastpump" %}</a></li>
|
||||||
|
<li class="breadcrumb-item active" aria-current="page">{% trans "Delete" %}</li>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<form role="form" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
<h1>Are you sure you want to delete <span class="text-info">{{ object }}</span>?</h1>
|
||||||
|
{% endblocktrans %}
|
||||||
|
<input type="submit" value="{% trans "Delete" %}" class="btn btn-danger" />
|
||||||
|
<a href="{% url 'core:breastpump-list' %}" class="btn btn-default">{% trans "Cancel" %}</a>
|
||||||
|
</form>
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,38 @@
|
||||||
|
{% extends 'babybuddy/page.html' %}
|
||||||
|
{% load datetime i18n %}
|
||||||
|
|
||||||
|
{% block title %}
|
||||||
|
{% if object %}
|
||||||
|
{{ object }}
|
||||||
|
{% else %}
|
||||||
|
{% trans "Add a Breastpump Reading" %}
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block breadcrumbs %}
|
||||||
|
<li class="breadcrumb-item"><a href="{% url 'core:breastpump-list' %}">{% trans "Breastpump" %}</a></li>
|
||||||
|
{% if object %}
|
||||||
|
<li class="breadcrumb-item active" aria-current="page">{% trans "Update" %}</li>
|
||||||
|
{% else %}
|
||||||
|
<li class="breadcrumb-item active" aria-current="page">{% trans "Add a Breastpump Reading" %}</li>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% if object %}
|
||||||
|
{% blocktrans trimmed %}
|
||||||
|
<h1>Update <span class="text-info">{{ object }}</span></h1>
|
||||||
|
{% endblocktrans %}
|
||||||
|
{% else %}
|
||||||
|
<h1>{% trans "Add a Breastpump Entry" %}</h1>
|
||||||
|
{% endif %}
|
||||||
|
{% include 'babybuddy/form.html' %}
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block javascript %}
|
||||||
|
<script type="text/javascript">
|
||||||
|
BabyBuddy.DatetimePicker.init($('#datetimepicker_time'), {
|
||||||
|
format: '{% datetimepicker_format %}'
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,73 @@
|
||||||
|
{% extends 'babybuddy/page.html' %}
|
||||||
|
{% load datetime i18n widget_tweaks %}
|
||||||
|
|
||||||
|
{% block title %}{% trans "Breastpump" %}{% endblock %}
|
||||||
|
|
||||||
|
{% block breadcrumbs %}
|
||||||
|
<li class="breadcrumb-item active" aria-current="page">{% trans "Breastpump" %}</li>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>
|
||||||
|
{% trans "Breastpump" %}
|
||||||
|
{% if perms.core.add_breastpump %}
|
||||||
|
<a href="{% url 'core:breastpump-add' %}" class="btn btn-sm btn-success">
|
||||||
|
<i class="icon-breastpump" aria-hidden="true"></i> {% trans "Add Breastpump Entry" %}
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
</h1>
|
||||||
|
{% include 'babybuddy/filter.html' %}
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table table-instances">
|
||||||
|
<thead class="thead-inverse">
|
||||||
|
<tr>
|
||||||
|
<th>{% trans "Actions" %}</th>
|
||||||
|
<th>{% trans "Time" %}</th>
|
||||||
|
{% if not unique_child %}
|
||||||
|
<th>{% trans "Child" %}</th>
|
||||||
|
{% endif %}
|
||||||
|
<th>{% trans "Amount" %}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for breastpump in object_list %}
|
||||||
|
{% cycle "odd" "even" as row_class silent %}
|
||||||
|
<tr class="{{ row_class }}">
|
||||||
|
<td>
|
||||||
|
<div class="btn-group btn-group-sm" role="group" aria-label="{% trans "Actions" %}">
|
||||||
|
|
||||||
|
{% if perms.core.change_breastpump %}
|
||||||
|
<a href="{% url 'core:breastpump-update' breastpump.id %}" class="btn btn-primary">
|
||||||
|
<i class="icon-update" aria-hidden="true"></i>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if perms.core.delete_breastpump %}
|
||||||
|
<a href="{% url 'core:breastpump-delete' breastpump.id %}" class="btn btn-danger">
|
||||||
|
<i class="icon-delete" aria-hidden="true"></i>
|
||||||
|
</a>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<th scope="row">{{ breastpump.time|datetime_short }}</th>
|
||||||
|
{% if not unique_child %}
|
||||||
|
<td><a href="{% url 'core:child' breastpump.child.slug %}">{{ breastpump.child }}</a></td>
|
||||||
|
{% endif %}
|
||||||
|
<td>{{ breastpump.amount }}</td>
|
||||||
|
</tr>
|
||||||
|
{% if breastpump.notes %}
|
||||||
|
<tr class="{{ row_class }} row-details">
|
||||||
|
<td colspan="4"><i class="icon-note mr-2" aria-hidden="true"></i>{{ breastpump.notes }}</td>
|
||||||
|
</tr>
|
||||||
|
{% endif %}
|
||||||
|
{% empty %}
|
||||||
|
<tr>
|
||||||
|
<th colspan="4">{% trans "No breastpump entries found." %}</th>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% include 'babybuddy/paginator.html' %}
|
||||||
|
{% endblock %}
|
12
core/urls.py
12
core/urls.py
|
@ -6,6 +6,18 @@ from . import views
|
||||||
app_name = "core"
|
app_name = "core"
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
|
path("breastpump/", views.BreastpumpList.as_view(), name="breastpump-list"),
|
||||||
|
path("breastpump/add/", views.BreastpumpAdd.as_view(), name="breastpump-add"),
|
||||||
|
path(
|
||||||
|
"breastpump/<int:pk>/",
|
||||||
|
views.BreastpumpUpdate.as_view(),
|
||||||
|
name="breastpump-update",
|
||||||
|
),
|
||||||
|
path(
|
||||||
|
"breastpump/<int:pk>/delete/",
|
||||||
|
views.BreastpumpDelete.as_view(),
|
||||||
|
name="breastpump-delete",
|
||||||
|
),
|
||||||
path("children/", views.ChildList.as_view(), name="child-list"),
|
path("children/", views.ChildList.as_view(), name="child-list"),
|
||||||
path("children/add/", views.ChildAdd.as_view(), name="child-add"),
|
path("children/add/", views.ChildAdd.as_view(), name="child-add"),
|
||||||
path("children/<str:slug>/", views.ChildDetail.as_view(), name="child"),
|
path("children/<str:slug>/", views.ChildDetail.as_view(), name="child"),
|
||||||
|
|
|
@ -121,6 +121,36 @@ class ChildDelete(CoreUpdateView):
|
||||||
return success_message % cleaned_data
|
return success_message % cleaned_data
|
||||||
|
|
||||||
|
|
||||||
|
class BreastpumpList(PermissionRequiredMixin, BabyBuddyFilterView):
|
||||||
|
model = models.Breastpump
|
||||||
|
template_name = "core/breastpump_list.html"
|
||||||
|
permission_required = ("core.view_breastpump",)
|
||||||
|
paginate_by = 10
|
||||||
|
filterset_fields = ("child",)
|
||||||
|
|
||||||
|
|
||||||
|
class BreastpumpAdd(CoreAddView):
|
||||||
|
model = models.Breastpump
|
||||||
|
permission_required = ("core.add_breastpump",)
|
||||||
|
form_class = forms.BreastpumpForm
|
||||||
|
success_url = reverse_lazy("core:breastpump-list")
|
||||||
|
success_message = _("%(model)s reading added!")
|
||||||
|
|
||||||
|
|
||||||
|
class BreastpumpUpdate(CoreUpdateView):
|
||||||
|
model = models.Breastpump
|
||||||
|
permission_required = ("core.change_breastpump",)
|
||||||
|
form_class = forms.BreastpumpForm
|
||||||
|
success_url = reverse_lazy("core:breastpump-list")
|
||||||
|
success_message = _("%(model)s reading for %(child)s updated.")
|
||||||
|
|
||||||
|
|
||||||
|
class BreastpumpDelete(CoreDeleteView):
|
||||||
|
model = models.Breastpump
|
||||||
|
permission_required = ("core.delete_breastpump",)
|
||||||
|
success_url = reverse_lazy("core:breastpump-list")
|
||||||
|
|
||||||
|
|
||||||
class DiaperChangeList(PermissionRequiredMixin, BabyBuddyFilterView):
|
class DiaperChangeList(PermissionRequiredMixin, BabyBuddyFilterView):
|
||||||
model = models.DiaperChange
|
model = models.DiaperChange
|
||||||
template_name = "core/diaperchange_list.html"
|
template_name = "core/diaperchange_list.html"
|
||||||
|
|
|
@ -11,6 +11,7 @@ authorization.
|
||||||
Currently, the following endpoints are available for `GET`, `OPTIONS`, and
|
Currently, the following endpoints are available for `GET`, `OPTIONS`, and
|
||||||
`POST` requests:
|
`POST` requests:
|
||||||
|
|
||||||
|
- `/api/breastpump/`
|
||||||
- `/api/children/`
|
- `/api/children/`
|
||||||
- `/api/changes/` (Diaper Changes)
|
- `/api/changes/` (Diaper Changes)
|
||||||
- `/api/feedings/`
|
- `/api/feedings/`
|
||||||
|
|
|
@ -45,6 +45,7 @@ ability to edit any entry.
|
||||||
|
|
||||||
The Measurements menu provides the option to view and track your baby's
|
The Measurements menu provides the option to view and track your baby's
|
||||||
measurements of temperature, weight, height, head circumference and BMI.
|
measurements of temperature, weight, height, head circumference and BMI.
|
||||||
|
This section also includes the mother's measurements for breastpump pumped.
|
||||||
|
|
||||||
Selecting any of the measurements will open that specific page with all related
|
Selecting any of the measurements will open that specific page with all related
|
||||||
measurements listed.
|
measurements listed.
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,4 @@
|
||||||
|
from .breastpump_amounts import breastpump_amounts # NOQA
|
||||||
from .diaperchange_amounts import diaperchange_amounts # NOQA
|
from .diaperchange_amounts import diaperchange_amounts # NOQA
|
||||||
from .diaperchange_lifetimes import diaperchange_lifetimes # NOQA
|
from .diaperchange_lifetimes import diaperchange_lifetimes # NOQA
|
||||||
from .diaperchange_types import diaperchange_types # NOQA
|
from .diaperchange_types import diaperchange_types # NOQA
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from django.utils import timezone
|
||||||
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
|
import plotly.offline as plotly
|
||||||
|
import plotly.graph_objs as go
|
||||||
|
|
||||||
|
from reports import utils
|
||||||
|
|
||||||
|
|
||||||
|
def breastpump_amounts(objects):
|
||||||
|
"""
|
||||||
|
Create a graph showing breastpump amounts over time.
|
||||||
|
:param instances: a QuerySet of Breastpump instances.
|
||||||
|
:returns: a tuple of the the graph's html and javascript.
|
||||||
|
"""
|
||||||
|
objects = objects.order_by("-time")
|
||||||
|
|
||||||
|
trace = go.Scatter(
|
||||||
|
name=_("Breastpump"),
|
||||||
|
x=list(objects.values_list("time", flat=True)),
|
||||||
|
y=list(objects.values_list("amount", flat=True)),
|
||||||
|
fill="tozeroy",
|
||||||
|
)
|
||||||
|
|
||||||
|
layout_args = utils.default_graph_layout_options()
|
||||||
|
layout_args["barmode"] = "stack"
|
||||||
|
layout_args["title"] = _("<b>Breastpump</b>")
|
||||||
|
layout_args["xaxis"]["title"] = _("Date")
|
||||||
|
layout_args["xaxis"]["rangeselector"] = utils.rangeselector_date()
|
||||||
|
layout_args["yaxis"]["title"] = _("Breastpump")
|
||||||
|
|
||||||
|
fig = go.Figure({"data": [trace], "layout": go.Layout(**layout_args)})
|
||||||
|
output = plotly.plot(fig, output_type="div", include_plotlyjs=False)
|
||||||
|
return utils.split_graph_output(output)
|
|
@ -0,0 +1,9 @@
|
||||||
|
{% extends 'reports/report_base.html' %}
|
||||||
|
{% load i18n %}
|
||||||
|
|
||||||
|
{% block title %}{% trans "Breastpump" %} - {{ object }}{% endblock %}
|
||||||
|
|
||||||
|
{% block breadcrumbs %}
|
||||||
|
{{ block.super }}
|
||||||
|
<li class="breadcrumb-item active" aria-current="page">{% trans "Breastpump" %}</li>
|
||||||
|
{% endblock %}
|
|
@ -8,6 +8,7 @@
|
||||||
<h1>Reports</h1>
|
<h1>Reports</h1>
|
||||||
<div class="list-group">
|
<div class="list-group">
|
||||||
<a href="{% url 'reports:report-bmi-bmi-child' object.slug %}" class="list-group-item list-group-item-action">{% trans "Body Mass Index (BMI)" %}</a>
|
<a href="{% url 'reports:report-bmi-bmi-child' object.slug %}" class="list-group-item list-group-item-action">{% trans "Body Mass Index (BMI)" %}</a>
|
||||||
|
<a href="{% url 'reports:report-breastpump-amounts-child' object.slug %}" class="list-group-item list-group-item-action">{% trans "Breastpump Amounts" %}</a>
|
||||||
<a href="{% url 'reports:report-diaperchange-amounts-child' object.slug %}" class="list-group-item list-group-item-action">{% trans "Diaper Change Amounts" %}</a>
|
<a href="{% url 'reports:report-diaperchange-amounts-child' object.slug %}" class="list-group-item list-group-item-action">{% trans "Diaper Change Amounts" %}</a>
|
||||||
<a href="{% url 'reports:report-diaperchange-types-child' object.slug %}" class="list-group-item list-group-item-action">{% trans "Diaper Change Types" %}</a>
|
<a href="{% url 'reports:report-diaperchange-types-child' object.slug %}" class="list-group-item list-group-item-action">{% trans "Diaper Change Types" %}</a>
|
||||||
<a href="{% url 'reports:report-diaperchange-lifetimes-child' object.slug %}" class="list-group-item list-group-item-action">{% trans "Diaper Lifetimes" %}</a>
|
<a href="{% url 'reports:report-diaperchange-lifetimes-child' object.slug %}" class="list-group-item list-group-item-action">{% trans "Diaper Lifetimes" %}</a>
|
||||||
|
|
|
@ -11,6 +11,11 @@ urlpatterns = [
|
||||||
views.ChildReportList.as_view(),
|
views.ChildReportList.as_view(),
|
||||||
name="report-list",
|
name="report-list",
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"children/<str:slug>/reports/breastpump/amounts/",
|
||||||
|
views.BreastpumpAmounts.as_view(),
|
||||||
|
name="report-breastpump-amounts-child",
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"children/<str:slug>/reports/changes/amounts/",
|
"children/<str:slug>/reports/changes/amounts/",
|
||||||
views.DiaperChangeAmounts.as_view(),
|
views.DiaperChangeAmounts.as_view(),
|
||||||
|
|
|
@ -17,6 +17,24 @@ class ChildReportList(PermissionRequiredMixin, DetailView):
|
||||||
template_name = "reports/report_list.html"
|
template_name = "reports/report_list.html"
|
||||||
|
|
||||||
|
|
||||||
|
class BreastpumpAmounts(PermissionRequiredMixin, DetailView):
|
||||||
|
"""
|
||||||
|
Graph of breastpump milk amounts collected.
|
||||||
|
"""
|
||||||
|
|
||||||
|
model = models.Child
|
||||||
|
permission_required = ("core.view_child",)
|
||||||
|
template_name = "reports/breastpump_amounts.html"
|
||||||
|
|
||||||
|
def get_context_data(self, **kwargs):
|
||||||
|
context = super(BreastpumpAmounts, self).get_context_data(**kwargs)
|
||||||
|
child = context["object"]
|
||||||
|
changes = models.Breastpump.objects.filter(child=child)
|
||||||
|
if changes and changes.count() > 0:
|
||||||
|
context["html"], context["js"] = graphs.breastpump_amounts(changes)
|
||||||
|
return context
|
||||||
|
|
||||||
|
|
||||||
class DiaperChangeAmounts(PermissionRequiredMixin, DetailView):
|
class DiaperChangeAmounts(PermissionRequiredMixin, DetailView):
|
||||||
"""
|
"""
|
||||||
Graph of diaper "amounts" - measurements of urine output.
|
Graph of diaper "amounts" - measurements of urine output.
|
||||||
|
|
|
@ -85,6 +85,8 @@
|
||||||
<glyph glyph-name="bmi" unicode="" d="M714 136q0 29-21 50t-50 21-50-21-22-50 22-50 50-22 50 22 21 50z m-428 428q0 29-21 51t-51 21-50-21-21-51 21-50 50-21 51 21 21 50z m571-428q0-89-63-152t-151-63-152 63-62 152 62 151 152 63 151-63 63-151z m-53 607q0-11-8-21l-589-786q-11-15-28-15h-90q-14 0-25 11t-10 25q0 11 7 21l589 786q11 15 29 15h89q14 0 25-11t11-25z m-375-179q0-88-63-151t-152-63-151 63-63 151 63 152 151 63 152-63 63-152z" horiz-adv-x="857.1" />
|
<glyph glyph-name="bmi" unicode="" d="M714 136q0 29-21 50t-50 21-50-21-22-50 22-50 50-22 50 22 21 50z m-428 428q0 29-21 51t-51 21-50-21-21-51 21-50 50-21 51 21 21 50z m571-428q0-89-63-152t-151-63-152 63-62 152 62 151 152 63 151-63 63-151z m-53 607q0-11-8-21l-589-786q-11-15-28-15h-90q-14 0-25 11t-10 25q0 11 7 21l589 786q11 15 29 15h89q14 0 25-11t11-25z m-375-179q0-88-63-151t-152-63-151 63-63 151 63 152 151 63 152-63 63-152z" horiz-adv-x="857.1" />
|
||||||
|
|
||||||
<glyph glyph-name="temperature" unicode="" d="M357 100q0-45-31-76t-76-31-76 31-31 76q0 34 19 61t52 40v363h72v-363q32-12 52-40t19-61z m72 0q0 43-19 80t-53 63v428q0 45-31 76t-76 32-76-32-31-76v-428q-34-25-53-63t-19-80q0-74 53-126t126-53 126 53 53 126z m71 0q0-103-73-177t-177-73-177 73-73 177q0 102 71 175v396q0 75 53 127t126 52 126-52 53-127v-396q71-73 71-175z m71 321v-71h-107v71h107z m0 143v-71h-107v71h107z m0 143v-71h-107v71h107z" horiz-adv-x="571.4" />
|
<glyph glyph-name="temperature" unicode="" d="M357 100q0-45-31-76t-76-31-76 31-31 76q0 34 19 61t52 40v363h72v-363q32-12 52-40t19-61z m72 0q0 43-19 80t-53 63v428q0 45-31 76t-76 32-76-32-31-76v-428q-34-25-53-63t-19-80q0-74 53-126t126-53 126 53 53 126z m71 0q0-103-73-177t-177-73-177 73-73 177q0 102 71 175v396q0 75 53 127t126 52 126-52 53-127v-396q71-73 71-175z m71 321v-71h-107v71h107z m0 143v-71h-107v71h107z m0 143v-71h-107v71h107z" horiz-adv-x="571.4" />
|
||||||
|
|
||||||
|
<glyph glyph-name="breastpump" unicode="" d="M290 28c9.333 78.667 29.333 151.667 60 219c30.667 67.333 61.333 120.333 92 159c30.667 38.667 58 84 82 136c24 52 36 105.333 36 160c0 76 -27.667 141.333 -83 196c-55.333 54.667 -121 82 -197 82c-76 0 -141.667 -27.333 -197 -82c-55.333 -54.667 -83 -120 -83 -196c0 -54.667 12 -108 36 -160c24 -52 51.333 -97.333 82 -136c30.667 -38.667 61.333 -91.667 92 -159c30.667 -67.333 50.667 -140.333 60 -219c1.333 -5.333 5 -8 11 -8c6 0 9 2.667 9 8c0 0 0 0 0 0m-42 392c1.333 -2.667 0.667 -7.333 -2 -14c-4 -4 -8.667 -6 -14 -6c-5.333 0 -9.333 2 -12 6c0 0 -40 58 -40 58c-21.333 30.667 -37.333 54 -48 70c-10.667 16 -22 41 -34 75c-12 34 -18 67.667 -18 101c0 16 5.667 29.667 17 41c11.333 11.333 25 17 41 17c38.667 0 58 -22.667 58 -68c0 -62.667 14 -144.667 42 -246c1.333 -4 3 -9.667 5 -17c2 -7.333 3.667 -13 5 -17c0 0 0 0 0 0" horiz-adv-x="571.4" />
|
||||||
</font>
|
</font>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
@ -85,6 +85,8 @@
|
||||||
<glyph glyph-name="bmi" unicode="" d="M714 136q0 29-21 50t-50 21-50-21-22-50 22-50 50-22 50 22 21 50z m-428 428q0 29-21 51t-51 21-50-21-21-51 21-50 50-21 51 21 21 50z m571-428q0-89-63-152t-151-63-152 63-62 152 62 151 152 63 151-63 63-151z m-53 607q0-11-8-21l-589-786q-11-15-28-15h-90q-14 0-25 11t-10 25q0 11 7 21l589 786q11 15 29 15h89q14 0 25-11t11-25z m-375-179q0-88-63-151t-152-63-151 63-63 151 63 152 151 63 152-63 63-152z" horiz-adv-x="857.1" />
|
<glyph glyph-name="bmi" unicode="" d="M714 136q0 29-21 50t-50 21-50-21-22-50 22-50 50-22 50 22 21 50z m-428 428q0 29-21 51t-51 21-50-21-21-51 21-50 50-21 51 21 21 50z m571-428q0-89-63-152t-151-63-152 63-62 152 62 151 152 63 151-63 63-151z m-53 607q0-11-8-21l-589-786q-11-15-28-15h-90q-14 0-25 11t-10 25q0 11 7 21l589 786q11 15 29 15h89q14 0 25-11t11-25z m-375-179q0-88-63-151t-152-63-151 63-63 151 63 152 151 63 152-63 63-152z" horiz-adv-x="857.1" />
|
||||||
|
|
||||||
<glyph glyph-name="temperature" unicode="" d="M357 100q0-45-31-76t-76-31-76 31-31 76q0 34 19 61t52 40v363h72v-363q32-12 52-40t19-61z m72 0q0 43-19 80t-53 63v428q0 45-31 76t-76 32-76-32-31-76v-428q-34-25-53-63t-19-80q0-74 53-126t126-53 126 53 53 126z m71 0q0-103-73-177t-177-73-177 73-73 177q0 102 71 175v396q0 75 53 127t126 52 126-52 53-127v-396q71-73 71-175z m71 321v-71h-107v71h107z m0 143v-71h-107v71h107z m0 143v-71h-107v71h107z" horiz-adv-x="571.4" />
|
<glyph glyph-name="temperature" unicode="" d="M357 100q0-45-31-76t-76-31-76 31-31 76q0 34 19 61t52 40v363h72v-363q32-12 52-40t19-61z m72 0q0 43-19 80t-53 63v428q0 45-31 76t-76 32-76-32-31-76v-428q-34-25-53-63t-19-80q0-74 53-126t126-53 126 53 53 126z m71 0q0-103-73-177t-177-73-177 73-73 177q0 102 71 175v396q0 75 53 127t126 52 126-52 53-127v-396q71-73 71-175z m71 321v-71h-107v71h107z m0 143v-71h-107v71h107z m0 143v-71h-107v71h107z" horiz-adv-x="571.4" />
|
||||||
|
|
||||||
|
<glyph glyph-name="breastpump" unicode="" d="M290 28c9.333 78.667 29.333 151.667 60 219c30.667 67.333 61.333 120.333 92 159c30.667 38.667 58 84 82 136c24 52 36 105.333 36 160c0 76 -27.667 141.333 -83 196c-55.333 54.667 -121 82 -197 82c-76 0 -141.667 -27.333 -197 -82c-55.333 -54.667 -83 -120 -83 -196c0 -54.667 12 -108 36 -160c24 -52 51.333 -97.333 82 -136c30.667 -38.667 61.333 -91.667 92 -159c30.667 -67.333 50.667 -140.333 60 -219c1.333 -5.333 5 -8 11 -8c6 0 9 2.667 9 8c0 0 0 0 0 0m-42 392c1.333 -2.667 0.667 -7.333 -2 -14c-4 -4 -8.667 -6 -14 -6c-5.333 0 -9.333 2 -12 6c0 0 -40 58 -40 58c-21.333 30.667 -37.333 54 -48 70c-10.667 16 -22 41 -34 75c-12 34 -18 67.667 -18 101c0 16 5.667 29.667 17 41c11.333 11.333 25 17 41 17c38.667 0 58 -22.667 58 -68c0 -62.667 14 -144.667 42 -246c1.333 -4 3 -9.667 5 -17c2 -7.333 3.667 -13 5 -17c0 0 0 0 0 0" horiz-adv-x="571.4" />
|
||||||
</font>
|
</font>
|
||||||
</defs>
|
</defs>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Loading…
Reference in New Issue