Fixed #34612 -- Fixed QuerySet.only() crash on reverse relationships.

Regression in b3db6c8dcb.

Thanks Ian Cubitt for the report.

This also corrected test_inheritance_deferred2() test which was
previously properly defined and marked as an expected failure but was
then wrongly adjusted to mask the lack of support for per-alias
deferral that was fixed by #21204.
This commit is contained in:
Simon Charette 2023-05-31 18:04:17 -04:00 committed by Mariusz Felisiak
parent d9e7018796
commit 2cf76f2d5d
4 changed files with 23 additions and 1 deletions

View File

@ -779,7 +779,13 @@ class Query(BaseExpression):
# Only include fields mentioned in the mask.
for field_name, field_mask in mask.items():
field = opts.get_field(field_name)
field_select_mask = select_mask.setdefault(field, {})
# Retrieve the actual field associated with reverse relationships
# as that's what is expected in the select mask.
if field in opts.related_objects:
field_key = field.field
else:
field_key = field
field_select_mask = select_mask.setdefault(field_key, {})
if field_mask:
if not field.is_relation:
raise FieldError(next(iter(field_mask)))

View File

@ -20,6 +20,9 @@ Bugfixes
when passing a ``ManyToManyField`` or ``GenericForeignKey`` reference. While
doing so is a no-op, it was allowed in older version (:ticket:`34570`).
* Fixed a regression in Django 4.2 that caused a crash of ``QuerySet.only()``
when passing a reverse ``OneToOneField`` reference (:ticket:`34612`).
* Fixed a bug in Django 4.2 where :option:`makemigrations --update` didn't
respect the ``--name`` option (:ticket:`34568`).

View File

@ -178,6 +178,16 @@ class DeferRegressionTest(TestCase):
self.assertEqual(i.one_to_one_item.name, "second")
with self.assertNumQueries(1):
self.assertEqual(i.value, 42)
with self.assertNumQueries(1):
i = Item.objects.select_related("one_to_one_item").only(
"name", "one_to_one_item__item"
)[0]
self.assertEqual(i.one_to_one_item.pk, o2o.pk)
self.assertEqual(i.name, "first")
with self.assertNumQueries(1):
self.assertEqual(i.one_to_one_item.name, "second")
with self.assertNumQueries(1):
self.assertEqual(i.value, 42)
def test_defer_with_select_related(self):
item1 = Item.objects.create(name="first", value=47)

View File

@ -249,6 +249,9 @@ class ReverseSelectRelatedTestCase(TestCase):
self.assertEqual(p.child1.name2, "n2")
p = qs.get(name2="n2")
with self.assertNumQueries(0):
self.assertEqual(p.child1.value, 1)
self.assertEqual(p.child1.child4.value4, 4)
with self.assertNumQueries(2):
self.assertEqual(p.child1.name1, "n1")
self.assertEqual(p.child1.child4.name1, "n1")