Opened 7 years ago
Last modified 7 years ago
#29367 closed Bug
bulk_create with manual primary_key don't update instances state — at Initial Version
Reported by: | Oscar Esgalha | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Normal | Keywords: | bulk_create, primary_key |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Given a model with manually defined primary keys:
class State(models.Model): two_letter_code = models.CharField(max_length=2, primary_key=True)
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:
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:
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