1
0
mirror of https://github.com/django/django.git synced 2025-10-31 09:41:08 +00:00

[5.1.x] Fixed #35950 -- Restored refreshing of relations when fields deferred.

Thank you to Simon Charette and Sarah Boyce for the review.

Regression in 73df8b54a2.

Backport of 2f6b096b83 from main.
This commit is contained in:
Adam Johnson
2024-11-30 08:03:55 +00:00
committed by Sarah Boyce
parent ee2698dcca
commit 6e3e7353e0
4 changed files with 31 additions and 9 deletions

View File

@@ -717,12 +717,13 @@ class Model(AltersData, metaclass=ModelBase):
if fields is not None:
db_instance_qs = db_instance_qs.only(*fields)
elif deferred_fields:
fields = {
db_instance_qs = db_instance_qs.only(
*{
f.attname
for f in self._meta.concrete_fields
if f.attname not in deferred_fields
}
db_instance_qs = db_instance_qs.only(*fields)
)
db_instance = db_instance_qs.get()
non_loaded_fields = db_instance.get_deferred_fields()
@@ -739,9 +740,9 @@ class Model(AltersData, metaclass=ModelBase):
field.delete_cached_value(self)
# Clear cached relations.
for field in self._meta.related_objects:
if (fields is None or field.name in fields) and field.is_cached(self):
field.delete_cached_value(self)
for rel in self._meta.related_objects:
if (fields is None or rel.name in fields) and rel.is_cached(self):
rel.delete_cached_value(self)
# Clear cached private relations.
for field in self._meta.private_fields:

View File

@@ -12,3 +12,7 @@ Bugfixes
* Fixed a crash in ``createsuperuser`` on Python 3.13+ caused by an unhandled
``OSError`` when the username could not be determined (:ticket:`35942`).
* Fixed a regression in Django 5.1 where relational fields were not updated
when calling ``Model.refresh_from_db()`` on instances with deferred fields
(:ticket:`35950`).

View File

@@ -57,6 +57,15 @@ class GenericForeignKeyTests(TestCase):
self.assertIsNot(answer.question, old_question_obj)
self.assertEqual(answer.question, old_question_obj)
def test_clear_cached_generic_relation_when_deferred(self):
question = Question.objects.create(text="question")
Answer.objects.create(text="answer", question=question)
answer = Answer.objects.defer("text").get()
old_question_obj = answer.question
# The reverse relation is refreshed even when the text field is deferred.
answer.refresh_from_db()
self.assertIsNot(answer.question, old_question_obj)
class GenericRelationTests(TestCase):
def test_value_to_string(self):

View File

@@ -290,6 +290,14 @@ class TestDefer2(AssertionMixin, TestCase):
self.assertEqual(rf2.name, "new foo")
self.assertEqual(rf2.value, "new bar")
def test_refresh_when_one_field_deferred(self):
s = Secondary.objects.create()
PrimaryOneToOne.objects.create(name="foo", value="bar", related=s)
s = Secondary.objects.defer("first").get()
p_before = s.primary_o2o
s.refresh_from_db()
self.assertIsNot(s.primary_o2o, p_before)
class InvalidDeferTests(SimpleTestCase):
def test_invalid_defer(self):