From a376e7e26383539779d52a5241f978d9dda37592 Mon Sep 17 00:00:00 2001 From: hcwinsemius Date: Thu, 2 Oct 2025 10:32:26 +0200 Subject: [PATCH] fix #109 --- CHANGELOG.md | 10 ++++++++++ LiveORC/settings.py | 4 ++-- api/serializers/__init__.py | 2 +- api/serializers/time_series.py | 9 +++++++++ api/tests/test_api_timeseries.py | 7 +++++++ api/views/time_series.py | 8 +++++++- 6 files changed, 36 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1907e02..21ee68b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +## [0.2.2] - 2025-10-02 +### Added +### Changed +### Deprecated +### Removed +### Fixed +- PATCH /api/site//timeseries/ was not working, now properly functions. +### Security + + ## [0.2.1] - 2025-07-01 ### Added ### Changed diff --git a/LiveORC/settings.py b/LiveORC/settings.py index 2c3b8fe..fb77e05 100644 --- a/LiveORC/settings.py +++ b/LiveORC/settings.py @@ -16,7 +16,7 @@ import boto3 # See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/ -VERSION = "0.2.1" +VERSION = "0.2.2" # Build paths inside the project like this: BASE_DIR / 'subdir'. # try to get BASE_DIR from env variable BASE_DIR = Path(__file__).resolve().parent.parent @@ -158,7 +158,7 @@ SPECTACULAR_SETTINGS = { 'TITLE': 'LiveORC API', 'DESCRIPTION': 'Live OpenRiverCam REST API and administrator dashboard', - 'VERSION': '0.1.0', + 'VERSION': VERSION, 'SERVE_INCLUDE_SCHEMA': False, # OTHER SETTINGS } diff --git a/api/serializers/__init__.py b/api/serializers/__init__.py index fe135a6..e266b0c 100644 --- a/api/serializers/__init__.py +++ b/api/serializers/__init__.py @@ -4,7 +4,7 @@ from .profile import ProfileSerializer, ProfileCreateSerializer from .recipe import RecipeSerializer from .video import VideoSerializer -from .time_series import TimeSeriesSerializer, TimeSeriesCreateSerializer +from .time_series import TimeSeriesSerializer, TimeSeriesCreateSerializer, TimeSeriesUpdateSerializer from .server import ServerSerializer from .task import TaskSerializer, TaskCreateSerializer from .task_form import TaskFormSerializer diff --git a/api/serializers/time_series.py b/api/serializers/time_series.py index 8933386..473f996 100644 --- a/api/serializers/time_series.py +++ b/api/serializers/time_series.py @@ -40,6 +40,7 @@ class Meta: def validate(self, data): user = User.objects.get(pk=self.initial_data["creator"]) institute_validator(institute=data.get("site").institute, user=user) + super().validate(data) return data class TimeSeriesCreateSerializer(TimeSeriesSerializer): @@ -51,3 +52,11 @@ class Meta: model = TimeSeries exclude = ("site", ) +class TimeSeriesUpdateSerializer(TimeSeriesCreateSerializer): + class Meta: + model = TimeSeries + exclude = ("site", "creator") + + def validate(self, data): + """Pass on the attributes as is, without user / creator / site check.""" + return data \ No newline at end of file diff --git a/api/tests/test_api_timeseries.py b/api/tests/test_api_timeseries.py index 6c2260d..3b18de1 100644 --- a/api/tests/test_api_timeseries.py +++ b/api/tests/test_api_timeseries.py @@ -41,6 +41,13 @@ def test_add_timeseries(self): ) self.assertEqual(r.status_code, status.HTTP_200_OK) + # try to patch a time series object + r = client.patch( + '/api/site/1/timeseries/1', + data={"h": 1.0}, + follow=True + ) + self.assertEqual(r.status_code, status.HTTP_200_OK) r = client.post( '/api/site/1/timeseries/', data={ diff --git a/api/views/time_series.py b/api/views/time_series.py index 17e0fe6..875c886 100644 --- a/api/views/time_series.py +++ b/api/views/time_series.py @@ -5,7 +5,7 @@ from rest_framework.decorators import renderer_classes from rest_framework.renderers import BrowsableAPIRenderer, JSONRenderer from rest_framework.response import Response -from api.serializers import TimeSeriesSerializer, TimeSeriesCreateSerializer +from api.serializers import TimeSeriesSerializer, TimeSeriesCreateSerializer, TimeSeriesUpdateSerializer from api.models import TimeSeries, Task, VideoStatus from api.task_utils import get_task from api.views import BaseModelViewSet @@ -35,6 +35,8 @@ class TimeSeriesViewSet(BaseModelViewSet): def get_serializer_class(self): if self.action == 'create': return TimeSeriesCreateSerializer + elif self.action in ['update', 'partial_update']: + return TimeSeriesUpdateSerializer return TimeSeriesSerializer def create(self, request, site_pk=None, *args, **kwargs): @@ -72,6 +74,10 @@ def create(self, request, site_pk=None, *args, **kwargs): headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) + def partial_update(self, request, *args, **kwargs): + return super().partial_update(request, *args, **kwargs) + + def get_queryset(self): # time series can also be retrieved nested per site, by filtering on the site of the cameraconfig property. return TimeSeries.objects.filter(site=self.kwargs['site_pk'])