Opened 6 years ago

Closed 6 years ago

Last modified 6 years ago

#29367 closed Bug (fixed)

bulk_create with manual primary_key don't update instances state

Reported by: Oscar Esgalha Owned by: Oscar Esgalha
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 (last modified by Oscar Esgalha)

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 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

Change History (8)

comment:1 by Oscar Esgalha, 6 years ago

Owner: changed from nobody to Oscar Esgalha
Status: newassigned

comment:2 by Oscar Esgalha, 6 years ago

comment:3 by Oscar Esgalha, 6 years ago

Description: modified (diff)

comment:4 by Simon Charette, 6 years ago

Has patch: set
Triage Stage: UnreviewedAccepted

comment:5 by Tim Graham <timograham@…>, 6 years ago

Resolution: fixed
Status: assignedclosed

In 6d1f576:

Fixed #29367 -- Fixed model state on objects with a primary key created with QuerySet.bulk_create().

comment:6 by Oscar Esgalha, 6 years ago

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

comment:7 by Tim Graham, 6 years ago

It doesn't qualify for a backport based on our supported versions policy.

comment:8 by Oscar Esgalha, 6 years ago

I see.
Thank you for the answer.

Note: See TracTickets for help on using tickets.
Back to Top