From 6d30969330441d2e47094e523e2a3610bb44b106 Mon Sep 17 00:00:00 2001 From: "Christopher C. Wells" Date: Fri, 27 May 2022 15:39:25 -0700 Subject: [PATCH] Reorder alpha API classes --- api/filters.py | 10 ++-- api/serializers.py | 67 +++++++++++++------------ api/tests.py | 118 ++++++++++++++++++++++----------------------- api/urls.py | 12 ++--- api/views.py | 71 +++++++++++++++------------ 5 files changed, 145 insertions(+), 133 deletions(-) diff --git a/api/filters.py b/api/filters.py index 979ff25f..b95c15e8 100644 --- a/api/filters.py +++ b/api/filters.py @@ -62,11 +62,6 @@ class StartEndFieldFilter(ChildFieldFilter): ) -class PumpingFilter(TimeFieldFilter): - class Meta(TimeFieldFilter.Meta): - model = models.Pumping - - class DiaperChangeFilter(TimeFieldFilter, TagsFieldFilter): class Meta(TimeFieldFilter.Meta): model = models.DiaperChange @@ -86,6 +81,11 @@ class NoteFilter(TimeFieldFilter, TagsFieldFilter): model = models.Note +class PumpingFilter(TimeFieldFilter): + class Meta(TimeFieldFilter.Meta): + model = models.Pumping + + class SleepFilter(StartEndFieldFilter, TagsFieldFilter): class Meta(StartEndFieldFilter.Meta): model = models.Sleep diff --git a/api/serializers.py b/api/serializers.py index 8d03fe12..9c3314fc 100644 --- a/api/serializers.py +++ b/api/serializers.py @@ -96,10 +96,13 @@ class TaggableSerializer(serializers.HyperlinkedModelSerializer): tags = TagListSerializerField(required=False) -class UserSerializer(serializers.ModelSerializer): +class BMISerializer(CoreModelSerializer, TaggableSerializer): class Meta: - model = User - fields = ("id", "username") + model = models.BMI + fields = ("id", "child", "bmi", "date", "notes", "tags") + extra_kwargs = { + "core.BMI.bmi": {"label": "BMI"}, + } class PumpingSerializer(CoreModelSerializer): @@ -148,6 +151,18 @@ class FeedingSerializer(CoreModelWithDurationSerializer, TaggableSerializer): ) +class HeadCircumferenceSerializer(CoreModelSerializer, TaggableSerializer): + class Meta: + model = models.HeadCircumference + fields = ("id", "child", "head_circumference", "date", "notes", "tags") + + +class HeightSerializer(CoreModelSerializer, TaggableSerializer): + class Meta: + model = models.Height + fields = ("id", "child", "height", "date", "notes", "tags") + + class NoteSerializer(CoreModelSerializer, TaggableSerializer): class Meta: model = models.Note @@ -160,6 +175,17 @@ class SleepSerializer(CoreModelWithDurationSerializer, TaggableSerializer): fields = ("id", "child", "start", "end", "duration", "nap", "notes", "tags") +class TagSerializer(serializers.HyperlinkedModelSerializer): + class Meta: + model = models.Tag + fields = ("slug", "name", "color", "last_used") + extra_kwargs = { + "slug": {"required": False, "read_only": True}, + "color": {"required": False}, + "last_used": {"required": False, "read_only": True}, + } + + class TemperatureSerializer(CoreModelSerializer, TaggableSerializer): class Meta: model = models.Temperature @@ -197,36 +223,13 @@ class TummyTimeSerializer(CoreModelWithDurationSerializer, TaggableSerializer): fields = ("id", "child", "start", "end", "duration", "milestone", "tags") +class UserSerializer(serializers.ModelSerializer): + class Meta: + model = User + fields = ("id", "username") + + class WeightSerializer(CoreModelSerializer, TaggableSerializer): class Meta: model = models.Weight fields = ("id", "child", "weight", "date", "notes", "tags") - - -class HeightSerializer(CoreModelSerializer, TaggableSerializer): - class Meta: - model = models.Height - fields = ("id", "child", "height", "date", "notes", "tags") - - -class HeadCircumferenceSerializer(CoreModelSerializer, TaggableSerializer): - class Meta: - model = models.HeadCircumference - fields = ("id", "child", "head_circumference", "date", "notes", "tags") - - -class BMISerializer(CoreModelSerializer, TaggableSerializer): - class Meta: - model = models.BMI - fields = ("id", "child", "bmi", "date", "notes", "tags") - - -class TagSerializer(serializers.HyperlinkedModelSerializer): - class Meta: - model = models.Tag - fields = ("slug", "name", "color", "last_used") - extra_kwargs = { - "slug": {"required": False, "read_only": True}, - "color": {"required": False}, - "last_used": {"required": False, "read_only": True}, - } diff --git a/api/tests.py b/api/tests.py index 0fe449ab..77258849 100644 --- a/api/tests.py +++ b/api/tests.py @@ -429,6 +429,65 @@ class SleepAPITestCase(TestBase.BabyBuddyAPITestCaseBase): self.assertEqual(response.data["end"], entry["end"]) +class TagsAPITestCase(TestBase.BabyBuddyAPITestCaseBase): + endpoint = reverse("api:tag-list") + model = models.Tag + + def test_get(self): + response = self.client.get(self.endpoint) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertDictEqual( + dict(response.data["results"][0]), + { + "name": "a name", + "slug": "a-name", + "color": "#FF0000", + "last_used": "2017-11-18T11:00:00-05:00", + }, + ) + + def test_post(self): + data = {"name": "new tag", "color": "#123456"} + response = self.client.post(self.endpoint, data, format="json") + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + + response = self.client.get(self.endpoint) + results = response.json()["results"] + results_by_name = {r["name"]: r for r in results} + + tag_data = results_by_name["new tag"] + self.assertDictContainsSubset(data, tag_data) + self.assertEqual(tag_data["slug"], "new-tag") + self.assertTrue(tag_data["last_used"]) + + def test_patch(self): + endpoint = f"{self.endpoint}a-name/" + + modified_data = { + "name": "A different name", + "color": "#567890", + } + response = self.client.patch( + endpoint, + modified_data, + ) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertDictContainsSubset(modified_data, response.data) + + def test_delete(self): + endpoint = f"{self.endpoint}a-name/" + response = self.client.delete(endpoint) + self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) + response = self.client.delete(endpoint) + self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) + + def test_post_tags_to_model(self): + data = {"child": 1, "note": "New tagged note.", "tags": ["tag1", "tag2"]} + response = self.client.post(reverse("api:note-list"), data, format="json") + self.assertEqual(response.status_code, status.HTTP_201_CREATED) + self.assertEqual(response.data["tags"], data["tags"]) + + class TemperatureAPITestCase(TestBase.BabyBuddyAPITestCaseBase): endpoint = reverse("api:temperature-list") model = models.Temperature @@ -667,62 +726,3 @@ class WeightAPITestCase(TestBase.BabyBuddyAPITestCaseBase): ) self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.data, entry) - - -class TagsAPITestCase(TestBase.BabyBuddyAPITestCaseBase): - endpoint = reverse("api:tag-list") - model = models.Tag - - def test_get(self): - response = self.client.get(self.endpoint) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertDictEqual( - dict(response.data["results"][0]), - { - "name": "a name", - "slug": "a-name", - "color": "#FF0000", - "last_used": "2017-11-18T11:00:00-05:00", - }, - ) - - def test_post(self): - data = {"name": "new tag", "color": "#123456"} - response = self.client.post(self.endpoint, data, format="json") - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - - response = self.client.get(self.endpoint) - results = response.json()["results"] - results_by_name = {r["name"]: r for r in results} - - tag_data = results_by_name["new tag"] - self.assertDictContainsSubset(data, tag_data) - self.assertEqual(tag_data["slug"], "new-tag") - self.assertTrue(tag_data["last_used"]) - - def test_patch(self): - endpoint = f"{self.endpoint}a-name/" - - modified_data = { - "name": "A different name", - "color": "#567890", - } - response = self.client.patch( - endpoint, - modified_data, - ) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertDictContainsSubset(modified_data, response.data) - - def test_delete(self): - endpoint = f"{self.endpoint}a-name/" - response = self.client.delete(endpoint) - self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT) - response = self.client.delete(endpoint) - self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND) - - def test_post_tags_to_model(self): - data = {"child": 1, "note": "New tagged note.", "tags": ["tag1", "tag2"]} - response = self.client.post(reverse("api:note-list"), data, format="json") - self.assertEqual(response.status_code, status.HTTP_201_CREATED) - self.assertEqual(response.data["tags"], data["tags"]) diff --git a/api/urls.py b/api/urls.py index 213994da..10382c71 100644 --- a/api/urls.py +++ b/api/urls.py @@ -6,20 +6,20 @@ from rest_framework.schemas import get_schema_view from . import views router = routers.DefaultRouter() -router.register(r"children", views.ChildViewSet) +router.register(r"bmi", views.BMIViewSet) router.register(r"changes", views.DiaperChangeViewSet) +router.register(r"children", views.ChildViewSet) router.register(r"feedings", views.FeedingViewSet) +router.register(r"head-circumference", views.HeadCircumferenceViewSet) +router.register(r"height", views.HeightViewSet) router.register(r"notes", views.NoteViewSet) -router.register(r"sleep", views.SleepViewSet) router.register(r"pumping", views.PumpingViewSet) +router.register(r"sleep", views.SleepViewSet) +router.register(r"tags", views.TagViewSet) router.register(r"temperature", views.TemperatureViewSet) router.register(r"timers", views.TimerViewSet) router.register(r"tummy-times", views.TummyTimeViewSet) router.register(r"weight", views.WeightViewSet) -router.register(r"height", views.HeightViewSet) -router.register(r"head-circumference", views.HeadCircumferenceViewSet) -router.register(r"bmi", views.BMIViewSet) -router.register(r"tags", views.TagViewSet) app_name = "api" diff --git a/api/views.py b/api/views.py index f8b7a9e3..c2101a81 100644 --- a/api/views.py +++ b/api/views.py @@ -9,6 +9,21 @@ from . import serializers, filters from .mixins import TimerFieldSupportMixin +class BMIViewSet(viewsets.ModelViewSet): + queryset = models.BMI.objects.all() + serializer_class = serializers.BMISerializer + filterset_fields = ("child", "date") + + def get_view_name(self): + """ + Gets the view name without changing the case of the model verbose name. + """ + name = models.BMI._meta.verbose_name + if self.suffix: + name += ' ' + self.suffix + return name + + class ChildViewSet(viewsets.ModelViewSet): queryset = models.Child.objects.all() serializer_class = serializers.ChildSerializer @@ -16,12 +31,6 @@ class ChildViewSet(viewsets.ModelViewSet): filterset_fields = ("first_name", "last_name", "slug", "birth_date") -class PumpingViewSet(viewsets.ModelViewSet): - queryset = models.Pumping.objects.all() - serializer_class = serializers.PumpingSerializer - filterset_class = filters.PumpingFilter - - class DiaperChangeViewSet(viewsets.ModelViewSet): queryset = models.DiaperChange.objects.all() serializer_class = serializers.DiaperChangeSerializer @@ -34,18 +43,43 @@ class FeedingViewSet(TimerFieldSupportMixin, viewsets.ModelViewSet): filterset_class = filters.FeedingFilter +class HeadCircumferenceViewSet(viewsets.ModelViewSet): + queryset = models.HeadCircumference.objects.all() + serializer_class = serializers.HeadCircumferenceSerializer + filterset_fields = ("child", "date") + + +class HeightViewSet(viewsets.ModelViewSet): + queryset = models.Height.objects.all() + serializer_class = serializers.HeightSerializer + filterset_fields = ("child", "date") + + class NoteViewSet(viewsets.ModelViewSet): queryset = models.Note.objects.all() serializer_class = serializers.NoteSerializer filterset_class = filters.NoteFilter +class PumpingViewSet(viewsets.ModelViewSet): + queryset = models.Pumping.objects.all() + serializer_class = serializers.PumpingSerializer + filterset_class = filters.PumpingFilter + + class SleepViewSet(TimerFieldSupportMixin, viewsets.ModelViewSet): queryset = models.Sleep.objects.all() serializer_class = serializers.SleepSerializer filterset_class = filters.SleepFilter +class TagViewSet(viewsets.ModelViewSet): + queryset = models.Tag.objects.all() + serializer_class = serializers.TagSerializer + lookup_field = "slug" + filterset_fields = ("last_used", "name") + + class TemperatureViewSet(viewsets.ModelViewSet): queryset = models.Temperature.objects.all() serializer_class = serializers.TemperatureSerializer @@ -80,28 +114,3 @@ class WeightViewSet(viewsets.ModelViewSet): queryset = models.Weight.objects.all() serializer_class = serializers.WeightSerializer filterset_fields = ("child", "date") - - -class HeightViewSet(viewsets.ModelViewSet): - queryset = models.Height.objects.all() - serializer_class = serializers.HeightSerializer - filterset_fields = ("child", "date") - - -class HeadCircumferenceViewSet(viewsets.ModelViewSet): - queryset = models.HeadCircumference.objects.all() - serializer_class = serializers.HeadCircumferenceSerializer - filterset_fields = ("child", "date") - - -class BMIViewSet(viewsets.ModelViewSet): - queryset = models.BMI.objects.all() - serializer_class = serializers.BMISerializer - filterset_fields = ("child", "date") - - -class TagViewSet(viewsets.ModelViewSet): - queryset = models.Tag.objects.all() - serializer_class = serializers.TagSerializer - lookup_field = "slug" - filterset_fields = ("last_used", "name")