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.

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