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.

209 lines
7.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
  9. from .models import DocumentAnnotation, SequenceAnnotation, Seq2seqAnnotation
  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')
  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 ProjectPolymorphicSerializer(PolymorphicSerializer):
  102. model_serializer_mapping = {
  103. Project: ProjectSerializer,
  104. TextClassificationProject: TextClassificationProjectSerializer,
  105. SequenceLabelingProject: SequenceLabelingProjectSerializer,
  106. Seq2seqProject: Seq2seqProjectSerializer
  107. }
  108. class ProjectFilteredPrimaryKeyRelatedField(serializers.PrimaryKeyRelatedField):
  109. def get_queryset(self):
  110. view = self.context.get('view', None)
  111. request = self.context.get('request', None)
  112. queryset = super(ProjectFilteredPrimaryKeyRelatedField, self).get_queryset()
  113. if not request or not queryset or not view:
  114. return None
  115. return queryset.filter(project=view.kwargs['project_id'])
  116. class DocumentAnnotationSerializer(serializers.ModelSerializer):
  117. # label = ProjectFilteredPrimaryKeyRelatedField(queryset=Label.objects.all())
  118. label = serializers.PrimaryKeyRelatedField(queryset=Label.objects.all())
  119. document = serializers.PrimaryKeyRelatedField(queryset=Document.objects.all())
  120. class Meta:
  121. model = DocumentAnnotation
  122. fields = ('id', 'prob', 'label', 'user', 'document')
  123. read_only_fields = ('user', )
  124. class SequenceAnnotationSerializer(serializers.ModelSerializer):
  125. #label = ProjectFilteredPrimaryKeyRelatedField(queryset=Label.objects.all())
  126. label = serializers.PrimaryKeyRelatedField(queryset=Label.objects.all())
  127. document = serializers.PrimaryKeyRelatedField(queryset=Document.objects.all())
  128. class Meta:
  129. model = SequenceAnnotation
  130. fields = ('id', 'prob', 'label', 'start_offset', 'end_offset', 'user', 'document')
  131. read_only_fields = ('user',)
  132. class Seq2seqAnnotationSerializer(serializers.ModelSerializer):
  133. document = serializers.PrimaryKeyRelatedField(queryset=Document.objects.all())
  134. class Meta:
  135. model = Seq2seqAnnotation
  136. fields = ('id', 'text', 'user', 'document', 'prob')
  137. read_only_fields = ('user',)
  138. class RoleSerializer(serializers.ModelSerializer):
  139. class Meta:
  140. model = Role
  141. fields = ('id', 'name')
  142. class RoleMappingSerializer(serializers.ModelSerializer):
  143. username = serializers.SerializerMethodField()
  144. rolename = serializers.SerializerMethodField()
  145. @classmethod
  146. def get_username(cls, instance):
  147. user = instance.user
  148. return user.username if user else None
  149. @classmethod
  150. def get_rolename(cls, instance):
  151. role = instance.role
  152. return role.name if role else None
  153. class Meta:
  154. model = RoleMapping
  155. fields = ('id', 'user', 'role', 'username', 'rolename')