From 289921e6c40dcdc1e1ace162210a237120a5dec1 Mon Sep 17 00:00:00 2001 From: Boris Sekachev Date: Wed, 21 Oct 2020 22:01:24 +0300 Subject: [PATCH] Updated api method to create review --- cvat/apps/authentication/auth.py | 5 ++- cvat/apps/engine/serializers.py | 27 +++++++++++----- cvat/apps/engine/views.py | 54 +++++++++++++++++++------------- 3 files changed, 54 insertions(+), 32 deletions(-) diff --git a/cvat/apps/authentication/auth.py b/cvat/apps/authentication/auth.py index 60bb2f18d8b2..d4e7869e3b2f 100644 --- a/cvat/apps/authentication/auth.py +++ b/cvat/apps/authentication/auth.py @@ -274,11 +274,10 @@ class JobChangePermission(BasePermission): def has_object_permission(self, request, view, obj): return request.user.has_perm('engine.job.change', obj) -class ReviewCreatePermission(BasePermission): +class JobReviewPermission(BasePermission): # pylint: disable=no-self-use def has_object_permission(self, request, view, obj): - db_job = obj.job - return request.user.has_perm('engine.job.review', db_job) + return request.user.has_perm('engine.job.review', obj) class IssueAccessPermission(BasePermission): # pylint: disable=no-self-use diff --git a/cvat/apps/engine/serializers.py b/cvat/apps/engine/serializers.py index aa824f5c40f6..e67022ed06e6 100644 --- a/cvat/apps/engine/serializers.py +++ b/cvat/apps/engine/serializers.py @@ -549,14 +549,25 @@ class Meta: read_only_fields = ('created_date', 'updated_date', 'id',) write_once_fields = ('issue', 'owner', ) -class IssueListSerializer(serializers.ListSerializer): - child = IssueSerializer() - -class CommentListSerializer(serializers.ListSerializer): - child = CommentSerializer() - class CombinedIssueSerializer(IssueSerializer): - comments = CommentListSerializer() + comment_set = CommentSerializer(many=True) class CombinedReviewSerializer(ReviewSerializer): - issues = CombinedIssueSerializer() + issue_set = CombinedIssueSerializer(many=True) + + def create(self, validated_data): + issues_validated_data = validated_data.pop('issue_set') + db_review = models.Review.objects.create(**validated_data) + for issue in issues_validated_data: + issue['review'] = db_review + + comments_validated_data = issue.pop('comment_set') + db_issue = models.Issue.objects.create(**issue) + for comment in comments_validated_data: + comment['issue'] = db_issue + models.Comment.objects.create(**comment) + + return db_review + +class CommentListSerializer(serializers.ListSerializer): + child = CommentSerializer() diff --git a/cvat/apps/engine/views.py b/cvat/apps/engine/views.py index f88b32a6cb83..0d913db29235 100644 --- a/cvat/apps/engine/views.py +++ b/cvat/apps/engine/views.py @@ -650,12 +650,15 @@ class JobViewSet(viewsets.GenericViewSet, def get_permissions(self): http_method = self.request.method + http_path = self.request.path permissions = [IsAuthenticated] if http_method in SAFE_METHODS: permissions.append(auth.JobAccessPermission) elif http_method in ["PATCH", "PUT", "DELETE"]: permissions.append(auth.JobChangePermission) + elif http_method == 'POST' and http_path.endswith('reviews/create'): + permissions.append(auth.JobReviewPermission) else: permissions.append(auth.AdminRolePermission) @@ -719,12 +722,36 @@ def reviews(self, request, pk): serializer = ReviewSerializer(queryset, many=True) return Response(serializer.data) + @swagger_auto_schema(method='post', operation_summary='Submit a review for the job') + @action(detail=True, methods=['POST'], url_path='reviews/create', serializer_class=CombinedReviewSerializer) + def create_review(self, request, pk): + db_job = self.get_object() + request.data.update({ + 'job': db_job.id, + 'reviewer': request.user.id, + 'assignee': db_job.assignee, + }) + + issue_set = request.data['issue_set'] + for issue in issue_set: + issue['job'] = db_job.id + issue['owner'] = request.user.id + comment_set = issue['comment_set'] + for comment in comment_set: + comment['owner'] = request.user.id + + serializer = CombinedReviewSerializer(data=request.data, partial=True) + if serializer.is_valid(raise_exception=True): + instance = serializer.save() + return Response(CombinedReviewSerializer(instance).data) + + @swagger_auto_schema(method='get', operation_summary='Get a brief summary about done reviews') - @action(detail=True, methods=['GET'], url_path='reviews/summary', serializer_class=ReviewSummarySerializer ) + @action(detail=True, methods=['GET'], url_path='reviews/summary', serializer_class=ReviewSummarySerializer) def reviews_summary(self, request, pk): db_job = self.get_object() - serialize = ReviewSummarySerializer(db_job) - return Response(serialize.data) + serializer = ReviewSummarySerializer(db_job) + return Response(serializer.data) @swagger_auto_schema(method='get', operation_summary='Method returns list of issues for the job', responses={'200': CombinedIssueSerializer(many=True)} @@ -736,28 +763,13 @@ def issues(self, request, pk): serializer = CombinedIssueSerializer(queryset, many=True) return Response(serializer.data) -@method_decorator(name='create', decorator=swagger_auto_schema(operation_summary='Method submits a review for a job')) @method_decorator(name='destroy', decorator=swagger_auto_schema(operation_summary='Method removes a review from a job')) -class ReviewViewSet(viewsets.GenericViewSet, mixins.CreateModelMixin, - mixins.DestroyModelMixin): +class ReviewViewSet(viewsets.GenericViewSet, mixins.DestroyModelMixin): queryset = Review.objects.all().order_by('id') - - def get_serializer_class(self): - http_method = self.request.method - if http_method == 'POST': - return CombinedReviewSerializer - else: - return ReviewSerializer + serializer_class = ReviewSerializer def get_permissions(self): - http_method = self.request.method - permissions = [IsAuthenticated] - - if http_method in ['POST']: - permissions.append(auth.ReviewCreatePermission) - else: - permissions.append(auth.AdminRolePermission) - + permissions = [IsAuthenticated, auth.AdminRolePermission] return [perm() for perm in permissions]