Performing a bulk_create with model instances will not correctly update
their state.
Looping through the instances and calling save() individually will result
in instances with different state from instances persisted with
bulk_create:
{{{
#!python
state_ca = State(two_letter_code='CA')
State.objects.bulk_create([state_ca])
state_ca._state.adding # => True
state_ca._state.db # => None
state_ny = State(two_letter_code='NY')
state_ny.save()
state_ny._state.adding # => False
state_ny._state.db # => 'default'
}}}
One implication of this behavior is that the instances saved with
bulk_create can't be used to build relationships with model instances
loaded with other Queryset API methods.
Here is a demonstration:
{{{
#!python
class Group(models.Model):
ext_id = models.CharField(primary_key=True, max_length=32)
class Analist(models.Model):
ext_id = models.CharField(primary_key=True, max_length=32)
groups = models.ManyToManyField(Group)
group_aaa = Group.objects.get(ext_id='AAA')
analist_eee = Analist(ext_id='EEE')
Analist.objects.bulk_create([analist_eee])
analist_eee.groups.set([group_aaa]) # ValueError: Cannot add "<Group:
AAA>": instance is on database "None", value is on database "default"
}}}
It fails when the `._state.db` is compared.
A current workaround option is to manually set the `._state.db` after the
bulk_create:
{{{
analist_eee = Analist(ext_id='EEE')
Analist.objects.bulk_create([analist_eee])
analist_eee._state.db = 'default'
analist_eee.groups.set([group_aaa]) # And now it works
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/29367>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* status: new => assigned
* owner: nobody => Oscar Esgalha
--
Ticket URL: <https://code.djangoproject.com/ticket/29367#comment:1>
Comment (by Oscar Esgalha):
PR with proposed fix:
https://github.com/django/django/pull/9902
--
Ticket URL: <https://code.djangoproject.com/ticket/29367#comment:2>
Old description:
New description:
class Analyst(models.Model):
ext_id = models.CharField(primary_key=True, max_length=32)
groups = models.ManyToManyField(Group)
group_aaa = Group.objects.get(ext_id='AAA')
analyst_eee = Analyst(ext_id='EEE')
Analyst.objects.bulk_create([analyst_eee])
analyst_eee.groups.set([group_aaa]) # ValueError: Cannot add "<Group:
AAA>": instance is on database "None", value is on database "default"
}}}
It fails when the `._state.db` is compared.
A current workaround option is to manually set the `._state.db` after the
bulk_create:
{{{
analyst_eee = Analyst(ext_id='EEE')
Analyst.objects.bulk_create([analyst_eee])
analyst_eee._state.db = 'default'
analyst_eee.groups.set([group_aaa]) # And now it works
}}}
--
--
Ticket URL: <https://code.djangoproject.com/ticket/29367#comment:3>
* has_patch: 0 => 1
* stage: Unreviewed => Accepted
--
Ticket URL: <https://code.djangoproject.com/ticket/29367#comment:4>
* status: assigned => closed
* resolution: => fixed
Comment:
In [changeset:"6d1f5769455ad8e1384087b92aa5839c3540d9ba" 6d1f576]:
{{{
#!CommitTicketReference repository=""
revision="6d1f5769455ad8e1384087b92aa5839c3540d9ba"
Fixed #29367 -- Fixed model state on objects with a primary key created
with QuerySet.bulk_create().
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/29367#comment:5>
Comment (by Oscar Esgalha):
Hi,
I'm glad the patch was accepted.
But I'd like to known if this can be backported to 1.11.x? Is there
anything I can do to help that?
Best regards
--
Ticket URL: <https://code.djangoproject.com/ticket/29367#comment:6>
Comment (by Tim Graham):
It doesn't qualify for a backport based on our
[https://docs.djangoproject.com/en/dev/internals/release-process
/#supported-versions supported versions policy].
--
Ticket URL: <https://code.djangoproject.com/ticket/29367#comment:7>
Comment (by Oscar Esgalha):
I see.
Thank you for the answer.
--
Ticket URL: <https://code.djangoproject.com/ticket/29367#comment:8>