diff --git a/api/libretime_api/mixins/__init__.py b/api/libretime_api/mixins/__init__.py new file mode 100644 index 000000000..53f66d3b4 --- /dev/null +++ b/api/libretime_api/mixins/__init__.py @@ -0,0 +1 @@ +from .readwriteserializer import ReadWriteSerializerMixin diff --git a/api/libretime_api/mixins/readwriteserializer.py b/api/libretime_api/mixins/readwriteserializer.py new file mode 100644 index 000000000..3f32c5eff --- /dev/null +++ b/api/libretime_api/mixins/readwriteserializer.py @@ -0,0 +1,33 @@ +from rest_framework.serializers import Serializer + + +class ReadWriteSerializerMixin: + """ + Overrides get_serializer_class to choose the read serializer + for GET requests and the write serializer for POST requests. + + Set read_serializer_class and write_serializer_class attributes on a + viewset. + """ + + read_serializer_class = Serializer + write_serializer_class = Serializer + + def get_serializer_class(self): + if self.action in ["create"]: + return self.get_write_serializer_class() + return self.get_read_serializer_class() + + def get_read_serializer_class(self): + assert self.read_serializer_class is not None, ( + f"'{self.__class__.__name__}' should either include a `read_serializer_class`" + "attribute, or override the `get_read_serializer_class()` method." + ) + return self.read_serializer_class + + def get_write_serializer_class(self): + assert self.write_serializer_class is not None, ( + f"'{self.__class__.__name__}' should either include a `write_serializer_class`" + "attribute, or override the `get_write_serializer_class()` method." + ) + return self.write_serializer_class diff --git a/api/libretime_api/schedule/serializers/__init__.py b/api/libretime_api/schedule/serializers/__init__.py index a10a4e771..a061fd6d6 100644 --- a/api/libretime_api/schedule/serializers/__init__.py +++ b/api/libretime_api/schedule/serializers/__init__.py @@ -1,5 +1,5 @@ from .playlist import PlaylistContentSerializer, PlaylistSerializer -from .schedule import ScheduleSerializer +from .schedule import ReadScheduleSerializer, WriteScheduleSerializer from .show import ( ShowDaysSerializer, ShowHostSerializer, diff --git a/api/libretime_api/schedule/serializers/schedule.py b/api/libretime_api/schedule/serializers/schedule.py index 56ff5b17d..9faa49be3 100644 --- a/api/libretime_api/schedule/serializers/schedule.py +++ b/api/libretime_api/schedule/serializers/schedule.py @@ -3,10 +3,17 @@ from rest_framework import serializers from ..models import Schedule -class ScheduleSerializer(serializers.ModelSerializer): +class ReadScheduleSerializer(serializers.ModelSerializer): cue_out = serializers.DurationField(source="get_cue_out", read_only=True) ends_at = serializers.DateTimeField(source="get_ends_at", read_only=True) class Meta: model = Schedule fields = "__all__" + + +class WriteScheduleSerializer(serializers.ModelSerializer): + + class Meta: + model = Schedule + fields = "__all__" diff --git a/api/libretime_api/schedule/views/schedule.py b/api/libretime_api/schedule/views/schedule.py index e933424b5..392d23378 100644 --- a/api/libretime_api/schedule/views/schedule.py +++ b/api/libretime_api/schedule/views/schedule.py @@ -2,8 +2,9 @@ from django.db import models from django_filters import rest_framework as filters from rest_framework import viewsets +from ...mixins import ReadWriteSerializerMixin from ..models import Schedule -from ..serializers import ScheduleSerializer +from ..serializers import ReadScheduleSerializer, WriteScheduleSerializer class ScheduleFilter(filters.FilterSet): @@ -26,8 +27,9 @@ class ScheduleFilter(filters.FilterSet): fields = [] # type: ignore -class ScheduleViewSet(viewsets.ModelViewSet): +class ScheduleViewSet(ReadWriteSerializerMixin, viewsets.ModelViewSet): queryset = Schedule.objects.all() - serializer_class = ScheduleSerializer + read_serializer_class = ReadScheduleSerializer + write_serializer_class = WriteScheduleSerializer filterset_class = ScheduleFilter model_permission_name = "schedule" diff --git a/api/schema.yml b/api/schema.yml index 054d1d074..9962bf882 100644 --- a/api/schema.yml +++ b/api/schema.yml @@ -2552,6 +2552,12 @@ paths: /api/v2/schedule: get: operationId: schedule_list + description: |- + Overrides get_serializer_class to choose the read serializer + for GET requests and the write serializer for POST requests. + + Set read_serializer_class and write_serializer_class attributes on a + viewset. parameters: - in: query name: broadcasted @@ -2597,23 +2603,29 @@ paths: schema: type: array items: - $ref: "#/components/schemas/Schedule" + $ref: "#/components/schemas/ReadSchedule" description: "" post: operationId: schedule_create + description: |- + Overrides get_serializer_class to choose the read serializer + for GET requests and the write serializer for POST requests. + + Set read_serializer_class and write_serializer_class attributes on a + viewset. tags: - schedule requestBody: content: application/json: schema: - $ref: "#/components/schemas/Schedule" + $ref: "#/components/schemas/WriteSchedule" application/x-www-form-urlencoded: schema: - $ref: "#/components/schemas/Schedule" + $ref: "#/components/schemas/WriteSchedule" multipart/form-data: schema: - $ref: "#/components/schemas/Schedule" + $ref: "#/components/schemas/WriteSchedule" required: true security: - cookieAuth: [] @@ -2623,11 +2635,17 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/Schedule" + $ref: "#/components/schemas/WriteSchedule" description: "" /api/v2/schedule/{id}: get: operationId: schedule_retrieve + description: |- + Overrides get_serializer_class to choose the read serializer + for GET requests and the write serializer for POST requests. + + Set read_serializer_class and write_serializer_class attributes on a + viewset. parameters: - in: path name: id @@ -2645,10 +2663,16 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/Schedule" + $ref: "#/components/schemas/ReadSchedule" description: "" put: operationId: schedule_update + description: |- + Overrides get_serializer_class to choose the read serializer + for GET requests and the write serializer for POST requests. + + Set read_serializer_class and write_serializer_class attributes on a + viewset. parameters: - in: path name: id @@ -2662,13 +2686,13 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/Schedule" + $ref: "#/components/schemas/ReadSchedule" application/x-www-form-urlencoded: schema: - $ref: "#/components/schemas/Schedule" + $ref: "#/components/schemas/ReadSchedule" multipart/form-data: schema: - $ref: "#/components/schemas/Schedule" + $ref: "#/components/schemas/ReadSchedule" required: true security: - cookieAuth: [] @@ -2678,10 +2702,16 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/Schedule" + $ref: "#/components/schemas/ReadSchedule" description: "" patch: operationId: schedule_partial_update + description: |- + Overrides get_serializer_class to choose the read serializer + for GET requests and the write serializer for POST requests. + + Set read_serializer_class and write_serializer_class attributes on a + viewset. parameters: - in: path name: id @@ -2695,13 +2725,13 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/PatchedSchedule" + $ref: "#/components/schemas/PatchedReadSchedule" application/x-www-form-urlencoded: schema: - $ref: "#/components/schemas/PatchedSchedule" + $ref: "#/components/schemas/PatchedReadSchedule" multipart/form-data: schema: - $ref: "#/components/schemas/PatchedSchedule" + $ref: "#/components/schemas/PatchedReadSchedule" security: - cookieAuth: [] - basicAuth: [] @@ -2710,10 +2740,16 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/Schedule" + $ref: "#/components/schemas/ReadSchedule" description: "" delete: operationId: schedule_destroy + description: |- + Overrides get_serializer_class to choose the read serializer + for GET requests and the write serializer for POST requests. + + Set read_serializer_class and write_serializer_class attributes on a + viewset. parameters: - in: path name: id @@ -6300,7 +6336,7 @@ components: user: type: integer nullable: true - PatchedSchedule: + PatchedReadSchedule: type: object properties: id: @@ -7096,41 +7132,7 @@ components: - id - key - user - RecordEnabledEnum: - enum: - - 0 - - 1 - type: integer - description: |- - * `0` - No - * `1` - Yes - RepeatKindEnum: - enum: - - 0 - - 1 - - 4 - - 5 - - 2 - type: integer - description: |- - * `0` - Every week - * `1` - Every 2 weeks - * `4` - Every 3 weeks - * `5` - Every 4 weeks - * `2` - Every month - RoleEnum: - enum: - - G - - H - - P - - A - type: string - description: |- - * `G` - Guest - * `H` - Host - * `P` - Manager - * `A` - Admin - Schedule: + ReadSchedule: type: object properties: id: @@ -7192,6 +7194,40 @@ components: - instance - position - starts_at + RecordEnabledEnum: + enum: + - 0 + - 1 + type: integer + description: |- + * `0` - No + * `1` - Yes + RepeatKindEnum: + enum: + - 0 + - 1 + - 4 + - 5 + - 2 + type: integer + description: |- + * `0` - Every week + * `1` - Every 2 weeks + * `4` - Every 3 weeks + * `5` - Every 4 weeks + * `2` - Every month + RoleEnum: + enum: + - G + - H + - P + - A + type: string + description: |- + * `G` - Guest + * `H` - Host + * `P` - Manager + * `A` - Admin ServiceRegister: type: object properties: @@ -7795,6 +7831,66 @@ components: * `4` - Friday * `5` - Saturday * `6` - Sunday + WriteSchedule: + type: object + properties: + id: + type: integer + readOnly: true + starts_at: + type: string + format: date-time + ends_at: + type: string + format: date-time + length: + type: string + nullable: true + fade_in: + type: string + format: time + nullable: true + fade_out: + type: string + format: time + nullable: true + cue_in: + type: string + cue_out: + type: string + position: + type: integer + maximum: 2147483647 + minimum: -2147483648 + position_status: + allOf: + - $ref: "#/components/schemas/PositionStatusEnum" + minimum: -32768 + maximum: 32767 + broadcasted: + type: integer + maximum: 32767 + minimum: -32768 + played: + type: boolean + nullable: true + instance: + type: integer + file: + type: integer + nullable: true + stream: + type: integer + nullable: true + required: + - broadcasted + - cue_in + - cue_out + - ends_at + - id + - instance + - position + - starts_at securitySchemes: basicAuth: type: http