Duplicate child objects on PUT request
Duplicate child objects on PUT request
Hey! Sorry, if it's already covered.
I am working on a non profit project and i've 3 levels of deeply nested models. Objects are created successfully when I use a POST request with below JSON data:
{
"id": "4c0e3383-aa2d-4ad9-8dc4-1a40bd910ca0",
"condition_block": {
"id": "343feaef-23c1-456b-b6e2-d955a86fde9b",
"referrer": {
"id": "4de8a35e-b00f-4e64-af0b-9a03f67dfbc1",
"list": [
"Google None Profit"
],
"kind": "CONTAINS"
},
"name": "Google Non Profit Works"
}
}
But when I issue a PUT request to /filters/4c0e3383-aa2d-4ad9-8dc4-1a40bd910ca0 with this JSON data:
{
"condition_block": {
"referrer": {
"list": [
"Google Non Profit"
],
"kind": "CONTAINS"
}
},
"name": "Google Non Profit Works"
}
It get this error:
IntegrityError at /api/v1/filters/4c0e3383-aa2d-4ad9-8dc4-1a40bd910ca0
duplicate key value violates unique constraint "api_conditionblock_filter_id_key"
DETAIL: Key (filter_id)=(4c0e3383-aa2d-4ad9-8dc4-1a40bd910ca0) already exists.
It just seems to create new child objects with the SAME parent id and fails.
Is this how it is designed to work?
Desired behavior
Fetch every child objects by ID and update them, especially when it's already known that they are in One to One relationship.
Models
class ReferrerCondition(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=200)
condition_block = models.OneToOneField(
ConditionBlock, null=True, related_name='referrer')
class ConditionBlock(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=200)
filter = models.OneToOneField(
Filter, null=True, related_name='condition_block')
class Filter(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=200)
Serializers
class ReferrerConditionSerializer(EnumFieldSerializerMixin,
serializers.ModelSerializer):
class Meta:
model = ReferrerCondition
exclude = ('condition_block', )
class ConditionBlockSerializer(WritableNestedModelSerializer):
referrer = ReferrerConditionSerializer()
class Meta:
model = ConditionBlock
exclude = ('filter', )
class FilterSerializer(EnumFieldSerializerMixin,
WritableNestedModelSerializer):
condition_block = ConditionBlockSerializer()
class Meta:
model = Filter
exclude = ()
Views
class FilterViewSet(viewsets.ModelViewSet):
queryset = Filter.objects.all()
serializer_class = FilterSerializer
Appears to be caused by https://github.com/beda-software/drf-writable-nested/issues/28
I believe this PR will fix it: https://github.com/beda-software/drf-writable-nested/pull/29
Hello @zero-master! The latest version 4.0.2 contains the fix of the problem with OneToOne updating without specifying id. I will appreciate if you check your code with the latest version of the package and leave feedback if everything is OK.
Hi, I have nested reverse relation (fk) which I try to update (there is a unique constraint on pk and additional field on in nested model). When I try to update it I've got IntegrityError: duplicate key value violates unique constraint. Seems that it try to create nested object instead of updating it.
However , it works when I pass directly 'id' for the nested object that is supposed to be updated in request:
works: "test_phase": [{"id": 4 ,"phase": "24h" , "result": "passed"}]
doeasn't: "test_phase": [{"phase": "24h" , "result": "passed"}]