﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
32190	Support for model relationships defined pre-save	Ryan Vinzent	nobody	"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:

{{{#!python
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:

{{{#!python
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.
{{{#!python
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."	Bug	closed	Database layer (models, ORM)	3.1	Normal	duplicate			Unreviewed	0	0	0	0	0	0
