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.

228 lines
8.2 KiB

6 years ago
5 years ago
6 years ago
6 years ago
6 years ago
5 years ago
5 years ago
5 years ago
6 years ago
5 years ago
6 years ago
6 years ago
6 years ago
  1. from django.conf import settings
  2. from django.contrib.auth import get_user_model
  3. from django.shortcuts import get_object_or_404
  4. from rest_framework import serializers
  5. from rest_polymorphic.serializers import PolymorphicSerializer
  6. from rest_framework.exceptions import ValidationError
  7. from .models import Label, Project, Document, RoleMapping, Role
  8. from .models import TextClassificationProject, SequenceLabelingProject, Seq2seqProject, Speech2textProject
  9. from .models import DocumentAnnotation, SequenceAnnotation, Seq2seqAnnotation, Speech2textAnnotation
  10. class UserSerializer(serializers.ModelSerializer):
  11. class Meta:
  12. model = get_user_model()
  13. fields = ('id', 'username', 'first_name', 'last_name', 'email', 'is_superuser')
  14. class LabelSerializer(serializers.ModelSerializer):
  15. def validate(self, attrs):
  16. prefix_key = attrs.get('prefix_key')
  17. suffix_key = attrs.get('suffix_key')
  18. # In the case of user don't set any shortcut key.
  19. if prefix_key is None and suffix_key is None:
  20. return super().validate(attrs)
  21. # Don't allow shortcut key not to have a suffix key.
  22. if prefix_key and not suffix_key:
  23. raise ValidationError('Shortcut key may not have a suffix key.')
  24. # Don't allow to save same shortcut key when prefix_key is null.
  25. try:
  26. context = self.context['request'].parser_context
  27. project_id = context['kwargs']['project_id']
  28. label_id = context['kwargs'].get('label_id')
  29. except (AttributeError, KeyError):
  30. pass # unit tests don't always have the correct context set up
  31. else:
  32. conflicting_labels = Label.objects.filter(
  33. suffix_key=suffix_key,
  34. prefix_key=prefix_key,
  35. project=project_id,
  36. )
  37. if label_id is not None:
  38. conflicting_labels = conflicting_labels.exclude(id=label_id)
  39. if conflicting_labels.exists():
  40. raise ValidationError('Duplicate shortcut key.')
  41. return super().validate(attrs)
  42. class Meta:
  43. model = Label
  44. fields = ('id', 'text', 'prefix_key', 'suffix_key', 'background_color', 'text_color')
  45. class DocumentSerializer(serializers.ModelSerializer):
  46. annotations = serializers.SerializerMethodField()
  47. annotation_approver = serializers.SerializerMethodField()
  48. def get_annotations(self, instance):
  49. request = self.context.get('request')
  50. project = instance.project
  51. model = project.get_annotation_class()
  52. serializer = project.get_annotation_serializer()
  53. annotations = model.objects.filter(document=instance.id)
  54. if request and not project.collaborative_annotation:
  55. annotations = annotations.filter(user=request.user)
  56. serializer = serializer(annotations, many=True)
  57. return serializer.data
  58. @classmethod
  59. def get_annotation_approver(cls, instance):
  60. approver = instance.annotations_approved_by
  61. return approver.username if approver else None
  62. class Meta:
  63. model = Document
  64. fields = ('id', 'text', 'annotations', 'meta', 'annotation_approver')
  65. class ProjectSerializer(serializers.ModelSerializer):
  66. current_users_role = serializers.SerializerMethodField()
  67. def get_current_users_role(self, instance):
  68. role_abstractor = {
  69. "is_project_admin": settings.ROLE_PROJECT_ADMIN,
  70. "is_annotator": settings.ROLE_ANNOTATOR,
  71. "is_annotation_approver": settings.ROLE_ANNOTATION_APPROVER,
  72. }
  73. queryset = RoleMapping.objects.values("role_id__name")
  74. if queryset:
  75. users_role = get_object_or_404(
  76. queryset, project=instance.id, user=self.context.get("request").user.id
  77. )
  78. for key, val in role_abstractor.items():
  79. role_abstractor[key] = users_role["role_id__name"] == val
  80. return role_abstractor
  81. class Meta:
  82. model = Project
  83. fields = ('id', 'name', 'description', 'guideline', 'users', 'current_users_role', 'project_type', 'image',
  84. 'updated_at', 'randomize_document_order', 'collaborative_annotation', 'single_class_classification')
  85. read_only_fields = ('image', 'updated_at', 'users', 'current_users_role')
  86. class TextClassificationProjectSerializer(ProjectSerializer):
  87. class Meta:
  88. model = TextClassificationProject
  89. fields = ProjectSerializer.Meta.fields
  90. read_only_fields = ProjectSerializer.Meta.read_only_fields
  91. class SequenceLabelingProjectSerializer(ProjectSerializer):
  92. class Meta:
  93. model = SequenceLabelingProject
  94. fields = ProjectSerializer.Meta.fields
  95. read_only_fields = ProjectSerializer.Meta.read_only_fields
  96. class Seq2seqProjectSerializer(ProjectSerializer):
  97. class Meta:
  98. model = Seq2seqProject
  99. fields = ProjectSerializer.Meta.fields
  100. read_only_fields = ProjectSerializer.Meta.read_only_fields
  101. class Speech2textProjectSerializer(ProjectSerializer):
  102. class Meta:
  103. model = Speech2textProject
  104. fields = ('id', 'name', 'description', 'guideline', 'users', 'current_users_role', 'project_type', 'image',
  105. 'updated_at', 'randomize_document_order')
  106. read_only_fields = ('image', 'updated_at', 'users', 'current_users_role')
  107. class ProjectPolymorphicSerializer(PolymorphicSerializer):
  108. model_serializer_mapping = {
  109. Project: ProjectSerializer,
  110. TextClassificationProject: TextClassificationProjectSerializer,
  111. SequenceLabelingProject: SequenceLabelingProjectSerializer,
  112. Seq2seqProject: Seq2seqProjectSerializer,
  113. Speech2textProject: Speech2textProjectSerializer,
  114. }
  115. class ProjectFilteredPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
  116. def get_queryset(self):
  117. view = self.context.get('view', None)
  118. request = self.context.get('request', None)
  119. queryset = super(ProjectFilteredPrimaryKeyRelatedField, self).get_queryset()
  120. if not request or not queryset or not view:
  121. return None
  122. return queryset.filter(project=view.kwargs['project_id'])
  123. class DocumentAnnotationSerializer(serializers.ModelSerializer):
  124. # label = ProjectFilteredPrimaryKeyRelatedField(queryset=Label.objects.all())
  125. label = serializers.PrimaryKeyRelatedField(queryset=Label.objects.all())
  126. document = serializers.PrimaryKeyRelatedField(queryset=Document.objects.all())
  127. class Meta:
  128. model = DocumentAnnotation
  129. fields = ('id', 'prob', 'label', 'user', 'document')
  130. read_only_fields = ('user', )
  131. class SequenceAnnotationSerializer(serializers.ModelSerializer):
  132. #label = ProjectFilteredPrimaryKeyRelatedField(queryset=Label.objects.all())
  133. label = serializers.PrimaryKeyRelatedField(queryset=Label.objects.all())
  134. document = serializers.PrimaryKeyRelatedField(queryset=Document.objects.all())
  135. class Meta:
  136. model = SequenceAnnotation
  137. fields = ('id', 'prob', 'label', 'start_offset', 'end_offset', 'user', 'document')
  138. read_only_fields = ('user',)
  139. class Seq2seqAnnotationSerializer(serializers.ModelSerializer):
  140. document = serializers.PrimaryKeyRelatedField(queryset=Document.objects.all())
  141. class Meta:
  142. model = Seq2seqAnnotation
  143. fields = ('id', 'text', 'user', 'document', 'prob')
  144. read_only_fields = ('user',)
  145. class Speech2textAnnotationSerializer(serializers.ModelSerializer):
  146. document = serializers.PrimaryKeyRelatedField(queryset=Document.objects.all())
  147. class Meta:
  148. model = Speech2textAnnotation
  149. fields = ('id', 'prob', 'text', 'user', 'document')
  150. read_only_fields = ('user',)
  151. class RoleSerializer(serializers.ModelSerializer):
  152. class Meta:
  153. model = Role
  154. fields = ('id', 'name')
  155. class RoleMappingSerializer(serializers.ModelSerializer):
  156. username = serializers.SerializerMethodField()
  157. rolename = serializers.SerializerMethodField()
  158. @classmethod
  159. def get_username(cls, instance):
  160. user = instance.user
  161. return user.username if user else None
  162. @classmethod
  163. def get_rolename(cls, instance):
  164. role = instance.role
  165. return role.name if role else None
  166. class Meta:
  167. model = RoleMapping
  168. fields = ('id', 'user', 'role', 'username', 'rolename')