diff --git a/changelog.d/20240514_201903_krishavrajsingh_duplicateAttribute.md b/changelog.d/20240514_201903_krishavrajsingh_duplicateAttribute.md new file mode 100644 index 000000000000..81fa2bcae8af --- /dev/null +++ b/changelog.d/20240514_201903_krishavrajsingh_duplicateAttribute.md @@ -0,0 +1,4 @@ +### Fixed + +- REST API allowed to create several attributes with the same name within one label + () diff --git a/cvat/apps/engine/serializers.py b/cvat/apps/engine/serializers.py index 200e4b001126..7a60922b89c0 100644 --- a/cvat/apps/engine/serializers.py +++ b/cvat/apps/engine/serializers.py @@ -321,6 +321,16 @@ def validate(self, attrs): return attrs + @staticmethod + def check_attribute_names_unique(attrs): + encountered_names = set() + for attribute in attrs: + attr_name = attribute.get('name') + if attr_name in encountered_names: + raise serializers.ValidationError(f"Duplicate attribute with name '{attr_name}' exists") + else: + encountered_names.add(attr_name) + @classmethod @transaction.atomic def update_label( @@ -336,6 +346,8 @@ def update_label( attributes = validated_data.pop('attributespec_set', []) + cls.check_attribute_names_unique(attributes) + if validated_data.get('id') is not None: try: db_label = models.Label.objects.get(id=validated_data['id'], **parent_info) @@ -451,6 +463,8 @@ def create_labels(cls, for label in labels: attributes = label.pop('attributespec_set') + cls.check_attribute_names_unique(attributes) + if label.get('id', None): del label['id']