"""Private and company-wide reusable task board templates.""" from django.db.models import Q from rest_framework import status, viewsets from rest_framework.decorators import action from rest_framework.exceptions import PermissionDenied from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from tasks.models import TaskBoardTemplate from tasks.realtime import send_task_board_update from tasks.templates import create_board_from_template from ..serializers.boards import TaskBoardSerializer from ..serializers.templates import ( TaskBoardTemplateInstantiateSerializer, TaskBoardTemplateSerializer, ) class TaskBoardTemplateViewSet(viewsets.ModelViewSet): permission_classes = [IsAuthenticated] serializer_class = TaskBoardTemplateSerializer def get_queryset(self): return ( TaskBoardTemplate.objects.filter( Q(is_shared=True) | Q(created_by=self.request.user) ) .select_related("created_by") .distinct() ) def get_object(self): template = super().get_object() if self.action in {"update", "partial_update", "destroy"}: self._require_owner(template) return template def perform_create(self, serializer): serializer.save(created_by=self.request.user) def _require_owner(self, template): if template.created_by_id != self.request.user.pk: raise PermissionDenied("Изменять шаблон может только его автор.") def perform_update(self, serializer): self._require_owner(serializer.instance) serializer.save() def perform_destroy(self, instance): self._require_owner(instance) instance.delete() @action(detail=True, methods=["post"], url_path="instantiate") def instantiate(self, request, pk=None): template = self.get_object() serializer = TaskBoardTemplateInstantiateSerializer(data=request.data) serializer.is_valid(raise_exception=True) name = serializer.validated_data.get("name") or template.name board = create_board_from_template(template, owner=request.user, name=name) send_task_board_update(board, "created", "board", board.id) return Response( TaskBoardSerializer(board, context={"request": request}).data, status=status.HTTP_201_CREATED, )