[Django] #29497: Initializing model instance with an unsaved related object, then saving that related object and then saving the instance doesn't work

27 views
Skip to first unread message

Django

unread,
Jun 15, 2018, 10:45:04 AM6/15/18
to django-...@googlegroups.com
#29497: Initializing model instance with an unsaved related object, then saving
that related object and then saving the instance doesn't work
-------------------------------------+-------------------------------------
Reporter: Robin | Owner: nobody
Ramael |
Type: Bug | Status: new
Component: Database | Version: master
layer (models, ORM) | Keywords: orm, foreign key,
Severity: Normal | bulk_create
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
Example:

{{{#!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.

Django

unread,
Jun 15, 2018, 2:13:50 PM6/15/18
to django-...@googlegroups.com
#29497: Initializing model instance with an unsaved related object, then saving
that related object and then saving the instance doesn't work
-------------------------------------+-------------------------------------
Reporter: Robin Ramael | Owner: nobody
Type: Bug | Status: closed
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution: duplicate
Keywords: orm, foreign key, | Triage Stage:
bulk_create | Unreviewed
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Tim Graham):

* status: new => closed
* resolution: => duplicate


Comment:

Duplicate of #29085.

--
Ticket URL: <https://code.djangoproject.com/ticket/29497#comment:1>

Django

unread,
Oct 23, 2020, 12:45:44 AM10/23/20
to django-...@googlegroups.com
#29497: Saving parent object after setting on child leads to unexpected data loss
in bulk_create().

-------------------------------------+-------------------------------------
Reporter: Robin Ramael | Owner: nobody
Type: Bug | Status: new

Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution:
Keywords: orm, foreign key, | Triage Stage: Accepted
bulk_create |
Has patch: 0 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak):

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

Django

unread,
Oct 26, 2020, 7:40:15 AM10/26/20
to django-...@googlegroups.com
#29497: Saving parent object after setting on child leads to unexpected data loss
in bulk_create().
-------------------------------------+-------------------------------------
Reporter: Robin Ramael | Owner: Hannes
| Ljungberg
Type: Bug | Status: closed

Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution: fixed

Keywords: orm, foreign key, | Triage Stage: Accepted
bulk_create |
Has patch: 1 | Needs documentation: 0

Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak <felisiak.mariusz@…>):

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

Reply all
Reply to author
Forward
0 new messages