#36344: Accessing a related field after using defer() or only() unexpectedly
overwrites unsaved state on model instances
-------------------------------------+-------------------------------------
Reporter: Erick | Owner: (none)
Type: Uncategorized | Status: closed
Component: Database layer | Version: 5.2
(models, ORM) |
Severity: Normal | Resolution: invalid
Keywords: | Triage Stage:
| Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Erick):
You're right, I over-simplified it. This appears to happen when:
1. An attribute is set on the model instance, and the name of the impacted
field ("value" in your example) is a substring of that attribute name;
2. The impacted field is accessed in the model instance constructor;
This repros on main:
{{{
diff --git a/tests/defer/models.py b/tests/defer/models.py
index 560e54c8c0..5b5f8fb86a 100644
--- a/tests/defer/models.py
+++ b/tests/defer/models.py
@@ -18,6 +18,9 @@ class Primary(models.Model):
def __str__(self):
return
self.name
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.value
class PrimaryOneToOne(models.Model):
name = models.CharField(max_length=50)
diff --git a/tests/defer/tests.py b/tests/defer/tests.py
index 989b5c63d7..11b7042a2f 100644
--- a/tests/defer/tests.py
+++ b/tests/defer/tests.py
@@ -360,3 +360,17 @@ class DeferredRelationTests(TestCase):
obj.second # Accessing a deferred field.
with self.assertNumQueries(0):
obj.primary_o2o
+
+
+ def test_related_fetching(self):
+ Primary.objects.create(
+ name="foo",
+ value="bar",
+ related=Secondary.objects.create(first="first",
second="second"),
+ )
+ primary = Primary.objects.only("name").first()
+ setattr(primary, "_any_value", "what")
+ primary.value = "ef"
+ self.assertEqual(primary.value, "ef")
+ primary.related
+ self.assertEqual(primary.value, "ef")
\ No newline at end of file
}}}
So it is a rather niche condition, admittedly. But still surprising.
--
Ticket URL: <
https://code.djangoproject.com/ticket/36344#comment:2>