You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

116 lines
3.8 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. import json
  2. import re
  3. from django.db import IntegrityError, transaction
  4. from django_filters.rest_framework import DjangoFilterBackend
  5. from rest_framework import generics, status
  6. from rest_framework.exceptions import ParseError
  7. from rest_framework.parsers import MultiPartParser
  8. from rest_framework.permissions import IsAuthenticated
  9. from rest_framework.response import Response
  10. from rest_framework.views import APIView
  11. from members.permissions import IsInProjectReadOnlyOrAdmin, IsProjectAdmin
  12. from ..exceptions import LabelValidationError
  13. from ..models import CategoryType, Label, RelationTypes, SpanType
  14. from ..serializers import (CategoryTypeSerializer, LabelSerializer,
  15. RelationTypesSerializer, SpanTypeSerializer)
  16. def camel_to_snake(name):
  17. name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
  18. return re.sub('([a-z0-9])([A-Z])', r'\1_\2', name).lower()
  19. def camel_to_snake_dict(d):
  20. return {camel_to_snake(k): v for k, v in d.items()}
  21. class LabelList(generics.ListCreateAPIView):
  22. model = Label
  23. filter_backends = [DjangoFilterBackend]
  24. serializer_class = LabelSerializer
  25. pagination_class = None
  26. permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin]
  27. def get_queryset(self):
  28. return self.model.objects.filter(project=self.kwargs['project_id'])
  29. def perform_create(self, serializer):
  30. serializer.save(project_id=self.kwargs['project_id'])
  31. def delete(self, request, *args, **kwargs):
  32. delete_ids = request.data['ids']
  33. self.model.objects.filter(pk__in=delete_ids).delete()
  34. return Response(status=status.HTTP_204_NO_CONTENT)
  35. class CategoryTypeList(LabelList):
  36. model = CategoryType
  37. serializer_class = CategoryTypeSerializer
  38. class CategoryTypeDetail(generics.RetrieveUpdateDestroyAPIView):
  39. queryset = CategoryType.objects.all()
  40. serializer_class = CategoryTypeSerializer
  41. lookup_url_kwarg = 'label_id'
  42. permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin]
  43. class SpanTypeList(LabelList):
  44. model = SpanType
  45. serializer_class = SpanTypeSerializer
  46. class SpanTypeDetail(generics.RetrieveUpdateDestroyAPIView):
  47. queryset = SpanType.objects.all()
  48. serializer_class = SpanTypeSerializer
  49. lookup_url_kwarg = 'label_id'
  50. permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin]
  51. class RelationTypeList(LabelList):
  52. model = RelationTypes
  53. serializer_class = RelationTypesSerializer
  54. class RelationTypeDetail(generics.RetrieveUpdateDestroyAPIView):
  55. queryset = RelationTypes.objects.all()
  56. serializer_class = RelationTypesSerializer
  57. lookup_url_kwarg = 'relation_type_id'
  58. permission_classes = [IsAuthenticated & IsInProjectReadOnlyOrAdmin]
  59. class LabelUploadAPI(APIView):
  60. parser_classes = (MultiPartParser,)
  61. permission_classes = [IsAuthenticated & IsProjectAdmin]
  62. serializer_class = LabelSerializer
  63. @transaction.atomic
  64. def post(self, request, *args, **kwargs):
  65. if 'file' not in request.data:
  66. raise ParseError('Empty content')
  67. try:
  68. labels = json.load(request.data['file'])
  69. labels = list(map(camel_to_snake_dict, labels))
  70. serializer = self.serializer_class(data=labels, many=True)
  71. serializer.is_valid(raise_exception=True)
  72. serializer.save(project_id=kwargs['project_id'])
  73. return Response(status=status.HTTP_201_CREATED)
  74. except json.decoder.JSONDecodeError:
  75. raise ParseError('The file format is invalid.')
  76. except IntegrityError:
  77. raise LabelValidationError
  78. class CategoryTypeUploadAPI(LabelUploadAPI):
  79. serializer_class = CategoryTypeSerializer
  80. class SpanTypeUploadAPI(LabelUploadAPI):
  81. serializer_class = SpanTypeSerializer
  82. class RelationTypeUploadAPI(LabelUploadAPI):
  83. serializer_class = RelationTypesSerializer