#36259: `_is_pk_set()` is incorrectly used to check for unsaved models.
-------------------------------------+-------------------------------------
Reporter: Clifford | Owner: Clifford Gama
Gama |
Type: Bug | Status: assigned
Component: Database | Version: dev
layer (models, ORM) |
Severity: Release | Keywords: _is_pk_set
blocker |
Triage Stage: | Has patch: 0
Unreviewed |
Needs documentation: 0 | Needs tests: 0
Patch needs improvement: 0 | Easy pickings: 0
UI/UX: 0 |
-------------------------------------+-------------------------------------
Since models defined with custom primary keys can have `pk` set before
being saved to the database, this means they bypass this as if they were
saved. Here is an example:
{{{#!diff
diff --git a/tests/one_to_one/tests.py b/tests/one_to_one/tests.py
index 451e97c274..67b1c32e90 100644
--- a/tests/one_to_one/tests.py
+++ b/tests/one_to_one/tests.py
@@ -170,6 +170,16 @@ class OneToOneTests(TestCase):
with self.assertRaises(Restaurant.DoesNotExist):
place.restaurant
+ def test_unsaved_object_with_supplied_primary_key(self):
+ link1 = Place.objects.create(name="Ushaka", address="Ethekwini")
+ link2 = ManualPrimaryKey(primary_key="YTREWQ", name="moonwalk")
+ msg = (
+ "save() prohibited to prevent data loss due to unsaved
related object "
+ "'link2'."
+ )
+ with self.assertRaisesMessage(ValueError, msg):
+ MultiModel.objects.create(link1=link1, link2=link2,
name="Unsavable")
+
def test_reverse_relationship_cache_cascade(self):
"""
Regression test for #9023: accessing the reverse relationship
shouldn't
}}}
which results in
{{{#!python
FE
======================================================================
ERROR: test_unsaved_object_with_supplied_primary_key
(one_to_one.tests.OneToOneTests.test_unsaved_object_with_supplied_primary_key)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/clifford/code/django/django/db/backends/sqlite3/base.py",
line 304, in check_constraints
raise IntegrityError(
django.db.utils.IntegrityError: The row in table 'one_to_one_multimodel'
with primary key '1' has an invalid foreign key:
one_to_one_multimodel.link2_id contains a value 'YTREWQ' that does not
have a corresponding value in one_to_one_manualprimarykey.primary_key.
======================================================================
FAIL: test_unsaved_object_with_supplied_primary_key
(one_to_one.tests.OneToOneTests.test_unsaved_object_with_supplied_primary_key)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/clifford/code/django/tests/one_to_one/tests.py", line 180,
in test_unsaved_object_with_supplied_primary_key
with self.assertRaisesMessage(ValueError, msg):
File "/usr/lib/python3.12/contextlib.py", line 144, in __exit__
next(self.gen)
AssertionError: ValueError not raised
----------------------------------------------------------------------
Ran 1 test in 0.004s
FAILED (failures=1, errors=1)
}}}
And here is the culprit
[https://github.com/django/django/blob/ef6a83789b310a441237a190a493c9586a4cb260/django/db/models/base.py#L1220C17-L1224C22
code]:
This is done in a few other places. My proposal is to replace such uses
cases of `_is_pk_set` with `instance._state.added` checks.
--
Ticket URL: <https://code.djangoproject.com/ticket/36259>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion visit
https://groups.google.com/d/msgid/django-updates/010701959dc9ace1-f1c91265-d0f0-4fc7-8d68-32e9e97eed71-000000%40eu-central-1.amazonses.com.