1
0
mirror of https://github.com/django/django.git synced 2024-12-22 00:55:44 +00:00

Fixed #35950 -- Restored refreshing of relations when fields deferred.

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

Regression in 73df8b54a2.
This commit is contained in:
Adam Johnson 2024-11-30 08:03:55 +00:00 committed by Sarah Boyce
parent 32b9e00b0c
commit 2f6b096b83
4 changed files with 31 additions and 9 deletions

View File

@ -726,12 +726,13 @@ class Model(AltersData, metaclass=ModelBase):
if fields is not None:
db_instance_qs = db_instance_qs.only(*fields)
elif deferred_fields:
fields = {
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_qs = db_instance_qs.only(
*{
f.attname
for f in self._meta.concrete_fields
if f.attname not in deferred_fields
}
)
db_instance = db_instance_qs.get()
non_loaded_fields = db_instance.get_deferred_fields()
@ -748,9 +749,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):