{{{#!python
class Country(models.Model):
name = models.CharField(max_length=255)
iso_two_letter = models.CharField(max_length=2)
description = models.TextField()
class City(models.Model):
name = models.CharField(max_length=255)
country = models.ForeignKey(Country, on_delete=models.CASCADE)
class BulkCreateTests(TestCase):
def test_fk_bug(self):
country_nl = Country(name='Netherlands', iso_two_letter='NL')
country_be = Country(name='Belgium', iso_two_letter='BE')
city = City(country=country_be, name='Brussels') # (1)
country_be.save() # (2)
city.save()
}}}
This results in an integrity error:
{{{
======================================================================
ERROR: test_fk_bug (bulk_create.tests.BulkCreateTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/robin/src/django/django/db/backends/utils.py", line 85, in
_execute
return self.cursor.execute(sql, params)
psycopg2.IntegrityError: null value in column "country_id" violates not-
null constraint
DETAIL: Failing row contains (1, Brussels, null).
The above exception was the direct cause of the following exception:
...
----------------------------------------------------------------------
}}}
I wonder wether there's a reason that this doesn't work. If setting a
related object on a model instance automatically sets
instance.related_object_id, you'd expect this behavior to continue working
if the related object receives its primary key after the referencing
instance was initialized.
Of course, switching lines (1) and (2) makes it all work, but this
behavior means that bulk creating with related objects (with postgres
returning the primary keys, bless it's heart) becomes more complex than it
should be, forcing the user to use mappings or even set the foreign keys
themselves:
{{{#!python
for country_data, city_data in data:
country = Country(**country_data)
countries.append(country)
city = City(country=country, **city_data)
cities.append(city)
Country.objects.bulk_create(countries)
# needs this for the bulk create to not give an integrity error:
for city in cities:
city.country_id = city.country.id
City.objects.bulk_create(cities)
}}}
Ideally, the main instance would, when saved, 'reach into' its related
objects and set the foreign key field like the loop does. Is there a
reason this can't work?
--
Ticket URL: <https://code.djangoproject.com/ticket/29497>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* status: new => closed
* resolution: => duplicate
Comment:
Duplicate of #29085.
--
Ticket URL: <https://code.djangoproject.com/ticket/29497#comment:1>
* status: closed => new
* resolution: duplicate =>
* stage: Unreviewed => Accepted
Comment:
Fix for this case was missing in the main ticket (#28147).
#32133 was closed as a duplicate.
--
Ticket URL: <https://code.djangoproject.com/ticket/29497#comment:2>
* status: assigned => closed
* resolution: => fixed
Comment:
In [changeset:"10f8b82d195caa3745ba37d9424893763f89653e" 10f8b82d]:
{{{
#!CommitTicketReference repository=""
revision="10f8b82d195caa3745ba37d9424893763f89653e"
Fixed #29497 -- Fixed loss of assigned parent when saving child with
bulk_create() after parent.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/29497#comment:4>