diff --git a/src/documents/serialisers.py b/src/documents/serialisers.py index 6fa4cd065..d5fc0f079 100644 --- a/src/documents/serialisers.py +++ b/src/documents/serialisers.py @@ -68,6 +68,25 @@ class MatchingModelSerializer(serializers.ModelSerializer): slug = SerializerMethodField() + def validate(self, data): + # see https://github.com/encode/django-rest-framework/issues/7173 + name = data["name"] if "name" in data else self.instance.name + owner = ( + data["owner"] + if "owner" in data + else self.user + if hasattr(self, "user") + else None + ) + if ("name" in data or "owner" in data) and self.Meta.model.objects.filter( + name=name, + owner=owner, + ).exists(): + raise serializers.ValidationError( + {"error": "Object violates owner / name unique constraint"}, + ) + return data + def validate_match(self, match): if ( "matching_algorithm" in self.initial_data @@ -188,7 +207,6 @@ class OwnedObjectSerializer(serializers.ModelSerializer, SetPermissionsMixin): self._set_permissions(validated_data["set_permissions"], instance) if "owner" in validated_data and "name" in self.Meta.fields: name = validated_data["name"] if "name" in validated_data else instance.name - print(name) not_unique = ( self.Meta.model.objects.exclude(pk=instance.pk) .filter(owner=validated_data["owner"], name=name) @@ -196,7 +214,7 @@ class OwnedObjectSerializer(serializers.ModelSerializer, SetPermissionsMixin): ) if not_unique: raise serializers.ValidationError( - "Object violates owner / name unique constraint", + {"error": "Object violates owner / name unique constraint"}, ) return super().update(instance, validated_data) diff --git a/src/documents/tests/test_api.py b/src/documents/tests/test_api.py index 6624bab05..419c7ffe9 100644 --- a/src/documents/tests/test_api.py +++ b/src/documents/tests/test_api.py @@ -1850,11 +1850,11 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): user1 = User.objects.create_user(username="test1") user2 = User.objects.create_user(username="test2") - self.client.post("/api/tags/", {"name": "tag 1"}, format="json") + response = self.client.post("/api/tags/", {"name": "tag 1"}, format="json") + self.assertEqual(response.status_code, status.HTTP_201_CREATED) - with transaction.atomic(): - with self.assertRaises(IntegrityError): - self.client.post("/api/tags/", {"name": "tag 1"}, format="json") + response = self.client.post("/api/tags/", {"name": "tag 1"}, format="json") + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.client.post( "/api/tags/", @@ -1862,14 +1862,26 @@ class TestDocumentApi(DirectoriesMixin, APITestCase): format="json", ) - try: - self.client.post( - "/api/tags/", - {"name": "tag 2", "owner": user2.pk}, - format="json", - ) - except IntegrityError as e: - assert False, f"Exception {e}" + response = self.client.post( + "/api/tags/", + {"name": "tag 2", "owner": user1.pk}, + format="json", + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + self.client.post( + "/api/tags/", + {"name": "tag 3", "owner": user1.pk}, + format="json", + ) + + response = self.client.post( + "/api/tags/", + {"name": "tag 3", "owner": user2.pk}, + format="json", + ) + + self.assertEqual(response.status_code, status.HTTP_201_CREATED) def test_tag_unique_name_and_owner_enforced_on_update(self): user1 = User.objects.create_user(username="test1")