oncall-engine/engine/common/ordered_model/viewset.py

57 lines
2 KiB
Python
Raw Permalink Normal View History

from rest_framework import serializers, status
from rest_framework.decorators import action
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from common.api_helpers.exceptions import BadRequest
from common.insight_log import EntityEvent, write_resource_insight_log
class OrderedModelViewSet(ModelViewSet):
"""Ordered model viewset to be used in internal API."""
@action(detail=True, methods=["put"])
def move_to_position(self, request: Request, pk: int) -> Response:
instance = self.get_object()
position = self._get_move_to_position_param(request)
prev_state = self._get_insight_logs_serialized(instance)
try:
instance.to_index(position)
except IndexError:
raise BadRequest(detail="Invalid position")
new_state = self._get_insight_logs_serialized(instance)
write_resource_insight_log(
instance=instance,
author=self.request.user,
event=EntityEvent.UPDATED,
prev_state=prev_state,
new_state=new_state,
)
return Response(status=status.HTTP_200_OK)
@staticmethod
def _get_insight_logs_serialized(instance):
try:
return instance.insight_logs_serialized
except AttributeError:
return instance.user.insight_logs_serialized # workaround for UserNotificationPolicy
@staticmethod
def _get_move_to_position_param(request: Request) -> int:
"""
Get "position" parameter from query params + validate it.
Used by actions on ordered models (e.g. move_to_position).
"""
class MoveToPositionQueryParamsSerializer(serializers.Serializer):
position = serializers.IntegerField()
serializer = MoveToPositionQueryParamsSerializer(data=request.query_params)
serializer.is_valid(raise_exception=True)
return serializer.validated_data["position"]