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.

243 lines
8.7 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, Comment
  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 CommentSerializer(serializers.ModelSerializer):
  46. class Meta:
  47. model = Comment
  48. fields = ('id', 'text', 'user')
  49. read_only_fields = ('user', 'document')
  50. class DocumentSerializer(serializers.ModelSerializer):
  51. annotations = serializers.SerializerMethodField()
  52. annotation_approver = serializers.SerializerMethodField()
  53. comments = CommentSerializer(many=True, read_only=True)
  54. def get_annotations(self, instance):
  55. request = self.context.get('request')
  56. project = instance.project
  57. model = project.get_annotation_class()
  58. serializer = project.get_annotation_serializer()
  59. annotations = model.objects.filter(document=instance.id)
  60. if request and not project.collaborative_annotation:
  61. annotations = annotations.filter(user=request.user)
  62. serializer = serializer(annotations, many=True)
  63. return serializer.data
  64. @classmethod
  65. def get_annotation_approver(cls, instance):
  66. approver = instance.annotations_approved_by
  67. return approver.username if approver else None
  68. class Meta:
  69. model = Document
  70. fields = ('id', 'text', 'annotations', 'meta', 'annotation_approver', 'comments')
  71. class ApproverSerializer(DocumentSerializer):
  72. class Meta:
  73. model = Document
  74. fields = ('id', 'annotation_approver')
  75. class ProjectSerializer(serializers.ModelSerializer):
  76. current_users_role = serializers.SerializerMethodField()
  77. def get_current_users_role(self, instance):
  78. role_abstractor = {
  79. "is_project_admin": settings.ROLE_PROJECT_ADMIN,
  80. "is_annotator": settings.ROLE_ANNOTATOR,
  81. "is_annotation_approver": settings.ROLE_ANNOTATION_APPROVER,
  82. }
  83. queryset = RoleMapping.objects.values("role_id__name")
  84. if queryset:
  85. users_role = get_object_or_404(
  86. queryset, project=instance.id, user=self.context.get("request").user.id
  87. )
  88. for key, val in role_abstractor.items():
  89. role_abstractor[key] = users_role["role_id__name"] == val
  90. return role_abstractor
  91. class Meta:
  92. model = Project
  93. fields = ('id', 'name', 'description', 'guideline', 'users', 'current_users_role', 'project_type',
  94. 'updated_at', 'randomize_document_order', 'collaborative_annotation', 'single_class_classification')
  95. read_only_fields = ('updated_at', 'users', 'current_users_role')
  96. class TextClassificationProjectSerializer(ProjectSerializer):
  97. class Meta:
  98. model = TextClassificationProject
  99. fields = ProjectSerializer.Meta.fields
  100. read_only_fields = ProjectSerializer.Meta.read_only_fields
  101. class SequenceLabelingProjectSerializer(ProjectSerializer):
  102. class Meta:
  103. model = SequenceLabelingProject
  104. fields = ProjectSerializer.Meta.fields
  105. read_only_fields = ProjectSerializer.Meta.read_only_fields
  106. class Seq2seqProjectSerializer(ProjectSerializer):
  107. class Meta:
  108. model = Seq2seqProject
  109. fields = ProjectSerializer.Meta.fields
  110. read_only_fields = ProjectSerializer.Meta.read_only_fields
  111. class Speech2textProjectSerializer(ProjectSerializer):
  112. class Meta:
  113. model = Speech2textProject
  114. fields = ('id', 'name', 'description', 'guideline', 'users', 'current_users_role', 'project_type',
  115. 'updated_at', 'randomize_document_order')
  116. read_only_fields = ('updated_at', 'users', 'current_users_role')
  117. class ProjectPolymorphicSerializer(PolymorphicSerializer):
  118. model_serializer_mapping = {
  119. Project: ProjectSerializer,
  120. TextClassificationProject: TextClassificationProjectSerializer,
  121. SequenceLabelingProject: SequenceLabelingProjectSerializer,
  122. Seq2seqProject: Seq2seqProjectSerializer,
  123. Speech2textProject: Speech2textProjectSerializer,
  124. }
  125. class ProjectFilteredPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
  126. def get_queryset(self):
  127. view = self.context.get('view', None)
  128. request = self.context.get('request', None)
  129. queryset = super(ProjectFilteredPrimaryKeyRelatedField, self).get_queryset()
  130. if not request or not queryset or not view:
  131. return None
  132. return queryset.filter(project=view.kwargs['project_id'])
  133. class DocumentAnnotationSerializer(serializers.ModelSerializer):
  134. # label = ProjectFilteredPrimaryKeyRelatedField(queryset=Label.objects.all())
  135. label = serializers.PrimaryKeyRelatedField(queryset=Label.objects.all())
  136. document = serializers.PrimaryKeyRelatedField(queryset=Document.objects.all())
  137. class Meta:
  138. model = DocumentAnnotation
  139. fields = ('id', 'prob', 'label', 'user', 'document', 'created_at', 'updated_at')
  140. read_only_fields = ('user', )
  141. class SequenceAnnotationSerializer(serializers.ModelSerializer):
  142. #label = ProjectFilteredPrimaryKeyRelatedField(queryset=Label.objects.all())
  143. label = serializers.PrimaryKeyRelatedField(queryset=Label.objects.all())
  144. document = serializers.PrimaryKeyRelatedField(queryset=Document.objects.all())
  145. class Meta:
  146. model = SequenceAnnotation
  147. fields = ('id', 'prob', 'label', 'start_offset', 'end_offset', 'user', 'document', 'created_at', 'updated_at')
  148. read_only_fields = ('user',)
  149. class Seq2seqAnnotationSerializer(serializers.ModelSerializer):
  150. document = serializers.PrimaryKeyRelatedField(queryset=Document.objects.all())
  151. class Meta:
  152. model = Seq2seqAnnotation
  153. fields = ('id', 'text', 'user', 'document', 'prob', 'created_at', 'updated_at')
  154. read_only_fields = ('user',)
  155. class Speech2textAnnotationSerializer(serializers.ModelSerializer):
  156. document = serializers.PrimaryKeyRelatedField(queryset=Document.objects.all())
  157. class Meta:
  158. model = Speech2textAnnotation
  159. fields = ('id', 'prob', 'text', 'user', 'document', 'created_at', 'updated_at')
  160. read_only_fields = ('user',)
  161. class RoleSerializer(serializers.ModelSerializer):
  162. class Meta:
  163. model = Role
  164. fields = ('id', 'name')
  165. class RoleMappingSerializer(serializers.ModelSerializer):
  166. username = serializers.SerializerMethodField()
  167. rolename = serializers.SerializerMethodField()
  168. @classmethod
  169. def get_username(cls, instance):
  170. user = instance.user
  171. return user.username if user else None
  172. @classmethod
  173. def get_rolename(cls, instance):
  174. role = instance.role
  175. return role.name if role else None
  176. class Meta:
  177. model = RoleMapping
  178. fields = ('id', 'user', 'role', 'username', 'rolename')