#36713: RecursionError with only() and fields usage in __init__
------------------------------+-----------------------------------------
Reporter: Michal Čihař | Type: Uncategorized
Status: new | Component: Uncategorized
Version: 5.2 | Severity: Normal
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------+-----------------------------------------
Django ends up in infinite recursion when combining `only()` and accessing
class attributes in `__init__`:
{{{
File "/tmp/django-recursion-test/app/models.py", line 14, in __init__
print(self.descriptions)
^^^^^^^^^^^^^^^^^
File "/tmp/django-test/lib/python3.13/site-
packages/django/db/models/query_utils.py", line 267, in __get__
instance.refresh_from_db(fields=[field_name])
~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
File "/tmp/django-test/lib/python3.13/site-
packages/django/db/models/base.py", line 758, in refresh_from_db
db_instance = db_instance_qs.get()
File "/tmp/django-test/lib/python3.13/site-
packages/django/db/models/query.py", line 633, in get
num = len(clone)
File "/tmp/django-test/lib/python3.13/site-
packages/django/db/models/query.py", line 370, in __len__
self._fetch_all()
~~~~~~~~~~~~~~~^^
File "/tmp/django-test/lib/python3.13/site-
packages/django/db/models/query.py", line 1995, in _fetch_all
self._result_cache = list(self._iterable_class(self))
~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/django-test/lib/python3.13/site-
packages/django/db/models/query.py", line 126, in __iter__
obj = model_cls.from_db(
db, init_list, row[model_fields_start:model_fields_end]
)
File "/tmp/django-test/lib/python3.13/site-
packages/django/db/models/base.py", line 605, in from_db
new = cls(*values)
File "/tmp/django-recursion-test/app/models.py", line 15, in __init__
print(self.notes)
^^^^^^^^^^
File "/tmp/django-test/lib/python3.13/site-
packages/django/db/models/query_utils.py", line 267, in __get__
instance.refresh_from_db(fields=[field_name])
~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^
File "/tmp/django-test/lib/python3.13/site-
packages/django/db/models/base.py", line 758, in refresh_from_db
db_instance = db_instance_qs.get()
File "/tmp/django-test/lib/python3.13/site-
packages/django/db/models/query.py", line 633, in get
num = len(clone)
File "/tmp/django-test/lib/python3.13/site-
packages/django/db/models/query.py", line 370, in __len__
self._fetch_all()
~~~~~~~~~~~~~~~^^
File "/tmp/django-test/lib/python3.13/site-
packages/django/db/models/query.py", line 1995, in _fetch_all
self._result_cache = list(self._iterable_class(self))
~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/django-test/lib/python3.13/site-
packages/django/db/models/query.py", line 126, in __iter__
obj = model_cls.from_db(
db, init_list, row[model_fields_start:model_fields_end]
)
File "/tmp/django-test/lib/python3.13/site-
packages/django/db/models/base.py", line 605, in from_db
new = cls(*values)
File "/tmp/django-recursion-test/app/models.py", line 14, in __init__
print(self.descriptions)
^^^^^^^^^^^^^^^^^
}}}
Preconditions for the error:
* Model with multiple fields
* Using at least two model fields in `__init__` (it does work fine with
accessing just one)
* Using `only()` with fields used in `__init__` but missing a field that
will be used later
To trigger this error, following model was used:
{{{
class Project(models.Model):
name = models.CharField(max_length=100)
slug = models.CharField(max_length=100)
descriptions = models.TextField()
notes = models.TextField()
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
print(self.descriptions)
print(self.notes)
}}}
And this is the code to trigger it:
{{{
Project.objects.create(name="Test", slug="test")
projects = Project.objects.only("descriptions", "notes")
# object is constructed and the field included only can be
accessed:
self.assertEqual(projects[0].notes, "")
# this fails with RecursionError
self.assertEqual(projects[0].slug, "test")
}}}
Reproduced with both Django 5.2 and 6.0b1.
Reproducing tests are available at
https://github.com/nijel/django-
recursion-test.
--
Ticket URL: <
https://code.djangoproject.com/ticket/36713>
Django <
https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.