Opened 4 years ago
Closed 4 years ago
#32660 closed Bug (invalid)
Endless loop upon delete
Reported by: | kr | Owned by: | exec-life |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 3.1 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
I have three models whereas one has a custom __init__()
method:
class Foo(models.Model): my_foo = models.CharField(max_length=1000) class Bar(models.Model): bar1 = models.CharField(max_length=1000, default="") bar2 = models.BooleanField(default=False) foo = models.ForeignKey(Foo, on_delete=models.CASCADE) def __init__(self, *args, **kwargs): super(Bar, self).__init__(*args, **kwargs) print("check") self._original_bar1 = self.bar1 self._original_bar2 = self.bar2 class Baz(models.Model): bar = models.ForeignKey(Bar, on_delete=models.CASCADE)
Creating a Foo object and a corresponding Bar object (via the admin interface) works fine.
However, when I delete the Foo object, this results in an endless loop of the __init__()
method.
If I rewrite the models slightly as
from django.db import models class Foo(models.Model): my_foo = models.CharField(max_length=1000) class AbstractBar2(models.Model): bar2 = models.BooleanField(default=False) def __init__(self, *args, **kwargs): super(AbstractBar2, self).__init__(*args, **kwargs) print("check") self._original_bar2 = self.bar2 class Meta: abstract = True class AbstractBar1(models.Model): bar1 = models.CharField(max_length=1000, default="") def __init__(self, *args, **kwargs): super(AbstractBar1, self).__init__(*args, **kwargs) print("check") self._original_bar1 = self.bar1 class Meta: abstract = True class Bar(AbstractBar1, AbstractBar2): foo = models.ForeignKey(Foo, on_delete=models.CASCADE) class Baz(models.Model): bar = models.ForeignKey(Bar, on_delete=models.CASCADE)
it errors out on
Fatal Python error: _Py_CheckRecursiveCall: Cannot recover from stack overflow. Python runtime state: initialized Current thread 0x000035d0 (most recent call first): File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\fields\__init__.py", line 807 in get_prep_value File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\fields\__init__.py", line 1770 in get_prep_value File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\lookups.py", line 76 in get_prep_lookup File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\lookups.py", line 24 in __init__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\sql\query.py", line 1165 in build_lookup File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\sql\query.py", line 1319 in build_filter File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\sql\query.py", line 1377 in _add_q File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\sql\query.py", line 1358 in add_q File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 969 in _filter_or_exclude_inplace File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 962 in _filter_or_exclude File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 942 in filter File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\manager.py", line 85 in manager_method File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 623 in refresh_from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query_utils.py", line 149 in __get__ File "C:\Users\name\PycharmProjects\djangoTest\foobar\models.py", line 26 in __init__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 513 in from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 71 in __iter__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 1308 in _fetch_all File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 269 in __len__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 425 in get File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 635 in refresh_from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query_utils.py", line 149 in __get__ File "C:\Users\name\PycharmProjects\djangoTest\foobar\models.py", line 14 in __init__ File "C:\Users\name\PycharmProjects\djangoTest\foobar\models.py", line 24 in __init__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 513 in from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 71 in __iter__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 1308 in _fetch_all File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 269 in __len__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 425 in get File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 635 in refresh_from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query_utils.py", line 149 in __get__ File "C:\Users\name\PycharmProjects\djangoTest\foobar\models.py", line 26 in __init__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 513 in from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 71 in __iter__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 1308 in _fetch_all File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 269 in __len__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 425 in get File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 635 in refresh_from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query_utils.py", line 149 in __get__ File "C:\Users\name\PycharmProjects\djangoTest\foobar\models.py", line 14 in __init__ File "C:\Users\name\PycharmProjects\djangoTest\foobar\models.py", line 24 in __init__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 513 in from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 71 in __iter__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 1308 in _fetch_all File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 269 in __len__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 425 in get File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 635 in refresh_from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query_utils.py", line 149 in __get__ File "C:\Users\name\PycharmProjects\djangoTest\foobar\models.py", line 26 in __init__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 513 in from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 71 in __iter__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 1308 in _fetch_all File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 269 in __len__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 425 in get File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 635 in refresh_from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query_utils.py", line 149 in __get__ File "C:\Users\name\PycharmProjects\djangoTest\foobar\models.py", line 14 in __init__ File "C:\Users\name\PycharmProjects\djangoTest\foobar\models.py", line 24 in __init__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 513 in from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 71 in __iter__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 1308 in _fetch_all File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 269 in __len__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 425 in get File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 635 in refresh_from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query_utils.py", line 149 in __get__ File "C:\Users\name\PycharmProjects\djangoTest\foobar\models.py", line 26 in __init__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 513 in from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 71 in __iter__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 1308 in _fetch_all File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 269 in __len__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 425 in get File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 635 in refresh_from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query_utils.py", line 149 in __get__ File "C:\Users\name\PycharmProjects\djangoTest\foobar\models.py", line 14 in __init__ File "C:\Users\name\PycharmProjects\djangoTest\foobar\models.py", line 24 in __init__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 513 in from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 71 in __iter__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 1308 in _fetch_all File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 269 in __len__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 425 in get File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 635 in refresh_from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query_utils.py", line 149 in __get__ File "C:\Users\name\PycharmProjects\djangoTest\foobar\models.py", line 26 in __init__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 513 in from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 71 in __iter__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 1308 in _fetch_all File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 269 in __len__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 425 in get File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 635 in refresh_from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query_utils.py", line 149 in __get__ File "C:\Users\name\PycharmProjects\djangoTest\foobar\models.py", line 14 in __init__ File "C:\Users\name\PycharmProjects\djangoTest\foobar\models.py", line 24 in __init__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 513 in from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 71 in __iter__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 1308 in _fetch_all File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 269 in __len__ File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query.py", line 425 in get File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\base.py", line 635 in refresh_from_db File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\db\models\query_utils.py", line 149 in __get__ File "C:\Users\name\PycharmProjects\djangoTest\foobar\models.py", line 26 in __init__ ... Thread 0x00000a60 (most recent call first): File "C:\Users\name\AppData\Local\Programs\Python\Python39\lib\selectors.py", line 315 in _select File "C:\Users\name\AppData\Local\Programs\Python\Python39\lib\selectors.py", line 324 in select File "C:\Users\name\AppData\Local\Programs\Python\Python39\lib\socketserver.py", line 232 in serve_forever File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\core\servers\basehttp.py", line 216 in run File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\core\management\commands\runserver.py", line 139 in inner_run File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\utils\autoreload.py", line 53 in wrapper File "C:\Users\name\AppData\Local\Programs\Python\Python39\lib\threading.py", line 888 in run File "C:\Users\name\AppData\Local\Programs\Python\Python39\lib\threading.py", line 950 in _bootstrap_inner File "C:\Users\name\AppData\Local\Programs\Python\Python39\lib\threading.py", line 908 in _bootstrap Thread 0x00000c7c (most recent call first): File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\utils\autoreload.py", line 374 in tick File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\utils\autoreload.py", line 324 in run_loop File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\utils\autoreload.py", line 318 in run File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\utils\autoreload.py", line 603 in start_django File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\utils\autoreload.py", line 618 in run_with_reloader File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\core\management\commands\runserver.py", line 103 in run File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\core\management\commands\runserver.py", line 96 in handle File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\core\management\base.py", line 371 in execute File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\core\management\commands\runserver.py", line 61 in execute File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\core\management\base.py", line 330 in run_from_argv File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\core\management\__init__.py", line 395 in execute File "C:\Users\name\PycharmProjects\global39\djangoTest\lib\site-packages\django\core\management\__init__.py", line 401 in execute_from_command_line File "C:\Users\name\PycharmProjects\djangoTest\manage.py", line 18 in main File "C:\Users\name\PycharmProjects\djangoTest\manage.py", line 22 in <module> Process finished with exit code -1
Change History (6)
follow-up: 3 comment:1 by , 4 years ago
comment:2 by , 4 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:3 by , 4 years ago
Replying to Tim Graham:
You should explain why Django is at fault and not your custom
__init__()
method, and ideally propose some solution.
The only thing my custom __init__()
method does is retrieving model attributes and saving them to local variables. I don't see why this should be illegal to do, especially because it works except when I try to perform the delete operations.
In my opinion, the code is simple enough that a "justification" why the __init__()
method is not at fault is not needed.
Obviously, django runs into an endless loop with the model initializations / fetching the model from the db. This clearly seems to be a fault of the django framework. Agreed?
comment:4 by , 4 years ago
Description: | modified (diff) |
---|
comment:5 by , 4 years ago
Your code will break as soon as fields are deferred which is something model deletion does to instantiate model instances while reducing memory and CPU usage during cascade deletion.
In other code your code breaks the Bar.objects.defer('bar1)
pattern because accessing fields triggers loading which is covered by the docs.
This is detailed a bit in #31475 but I suggest you avoid overriding __init__
and favour from_db_value
and rely on fields
instead of if you cannot do self.__dict__.get('bar1')
to bypass deferred attributes descriptors.
comment:6 by , 4 years ago
Resolution: | → invalid |
---|---|
Status: | assigned → closed |
Type: | Uncategorized → Bug |
You should explain why Django is at fault and not your custom
__init__()
method, and ideally propose some solution.