Opened 4 years ago
Closed 4 years ago
#32190 closed Bug (duplicate)
Support for model relationships defined pre-save
Reported by: | Ryan Vinzent | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 3.1 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
There are many situations where it is optimal to define a bunch of objects, and then later commit them in bulk. When the objects define a FK relationship, this strategy requires a bit of hacking that I would prefer not to do. Take the following example:
class Parent(models.Model): name = models.TextField() class Child(models.Model): name = models.TextField() parent = models.ForeignKey(Parent, on_delete=models.RESTRICT)
Now if we have some function that defines a bunch of these objects to later commit them in bulk:
def build_objects(parent_child_mapping): parents = [] children = [] # {"father": ["son", "daughter"], ...} for parent_name, child_names in parent_child_mapping.items(): parent = Parent(name=parent_name) parents.append(parent) children.extend(Child(parent=parent, name=child_name) for child_name in child_names) # now commit all objects in bulk Parent.objects.bulk_create(parents) # fails with IntegrityError: parent_id is not nullable Child.objects.bulk_create(children)
I would expect the above to work fine, given the parent ID's are known when inserting the children, however this would throw an IntegrityError
because parent_id
on the Child
objects is still None
.
Adding a simple hack to the function will let it work fine, but it's annoying to do this everywhere where this pattern of creating objects is followed.
def build_objects(parent_child_mapping): parents = [] children = [] for parent_name, child_names in parent_child_mapping.items(): parent = Parent(name=parent_name) parents.append(parent) children.extend(Child(parent=parent, name=child_name) for child_name in child_names) # now commit all objects in bulk Parent.objects.bulk_create(parents) # add hack to make sure object IDs are properly assigned for child in children: child.parent_id = child.parent.id # now this call can succeed Child.objects.bulk_create(children)
This seems like something that should be supported by Django, and I believe this would make the ORM more consistent overall.
Thanks.
Change History (1)
comment:1 by , 4 years ago
Resolution: | → duplicate |
---|---|
Status: | new → closed |
Type: | New feature → Bug |
Duplicate of #29497. It was fixed in 10f8b82d195caa3745ba37d9424893763f89653e (Django 3.2+).