Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question about usage of allow_create and allow_nested_updates #63

Open
orientalperil opened this issue Oct 30, 2020 · 3 comments
Open

Comments

@orientalperil
Copy link

I'm a little confused about the intended way to use allow_create and allow_nested_updates. From what I can understand allow_create means that if there isn't a related record a blank model will be instantiated:

elif validated_data is not None and self.allow_create:
return self.model()

There seems to be an inconsistency in how allow_create is used when the nested serializer is a ListSerializer (many=True) versus when it is a BaseSerializer.

As a ListSerializer setting allow_create=True implies allow_nested_updates=True because the related object will be treated the same way:

for item in validated_data.get(field.source):
child_instance = field.child.get_object(item)
if child_instance and (field.child.allow_create or field.child.allow_nested_updates):
v = field.child.perform_update(child_instance, item, errors)
else:
v = child_instance
if v:
value.append(v)

But as a BaseSerializer setting allow_create=True alone will instantiate a blank model but will not update it unless you also set allow_nested_updates=True:

if field.source == "*":
value = validated_data
child_instance = instance
else:
if field.source not in validated_data:
continue
value = validated_data.get(field.source)
child_instance = getattr(instance, field.source, None)
child_instance = field.get_object(value, child_instance)
if child_instance and field.allow_nested_updates:
value = field.perform_update(child_instance, value, errors)
else:
value = child_instance

Setting allow_create=True alone will save the nested serializer with null for all values.

I can't tell if this difference in behavior is intentional or a bug. Can you clarify about how allow_create is supposed to be used?

@shosca
Copy link
Owner

shosca commented Nov 2, 2020

Yes, that is correct. allow_create controls what to do when a nested instance is not found and allow_nested_updates controls updating the nested instance. There's an edge case where allow_create can be True with allow_nested_update being False where you can end up being able to create blank nested instances

@orientalperil
Copy link
Author

Ok thanks for the confirmation. Is there a reason why the ListSerializer applies allow_create as implying allow_nested_updates? If not I think it could be better to treat ListSerializer and BaseSerializer by the same rules one way or the other. Or at least for a BaseSerializer if you set allow_create but not allow_nested_updates then there could be a warning logged.

@shosca
Copy link
Owner

shosca commented Nov 6, 2020

I think i see what you're talking about, here:

for item in validated_data.get(field.source):
child_instance = field.child.get_object(item)
if child_instance and (field.child.allow_create or field.child.allow_nested_updates):
v = field.child.perform_update(child_instance, item, errors)
else:
v = child_instance
if v:
value.append(v)

the check on field.child.allow_create on 786 is unnecessary since the above field.child.get_object(item) will already check for allow_create

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants