django-model-utils icon indicating copy to clipboard operation
django-model-utils copied to clipboard

Django 3 with 4.0.0 causes stack overflow on cascade delete of tracker field models

Open wagmiwiz opened this issue 4 years ago • 3 comments

Problem

When using 4.0.0 with Django 3.0.3 an stack overflow is caused when doing a queryset .delete() which causes a cascade delete of a model with a tracker field.

Environment

  • Django Model Utils version: 4.0.0
  • Django version: 3.0.3
  • Python version: 3.6
  • Other libraries used, if any: -

Stack trace

I don't have a separate code sandbox/test case, but for now here is a stack trace:

Keeps repeating:

  File ".../lib/python3.6/site-packages/django/db/models/query.py", line 1261 in _fetch_all
  File ".../lib/python3.6/site-packages/django/db/models/query.py", line 258 in __len__
  File ".../lib/python3.6/site-packages/django/db/models/query.py", line 411 in get
  File ".../lib/python3.6/site-packages/django/db/models/base.py", line 627 in refresh_from_db
  File ".../lib/python3.6/site-packages/django/db/models/query_utils.py", line 139 in __get__
  File ".../lib/python3.6/site-packages/model_utils/tracker.py", line 100 in get_field_value
  File ".../lib/python3.6/site-packages/model_utils/tracker.py", line 126 in <dictcomp>
  File ".../lib/python3.6/site-packages/model_utils/tracker.py", line 126 in current
  File ".../lib/python3.6/site-packages/model_utils/tracker.py", line 106 in set_saved_fields
  File ".../lib/python3.6/site-packages/model_utils/tracker.py", line 232 in initialize_tracker
  File ".../lib/python3.6/site-packages/django/dispatch/dispatcher.py", line 175 in <listcomp>
  File ".../lib/python3.6/site-packages/django/dispatch/dispatcher.py", line 175 in send
  File ".../lib/python3.6/site-packages/django/db/models/base.py", line 502 in __init__
  File ".../lib/python3.6/site-packages/django/db/models/base.py", line 512 in from_db
  File ".../lib/python3.6/site-packages/django/db/models/query.py", line 75 in __iter__
  File ".../lib/python3.6/site-packages/django/db/models/query.py", line 1261 in _fetch_all
  File ".../lib/python3.6/site-packages/django/db/models/query.py", line 258 in __len__
  File ".../lib/python3.6/site-packages/django/db/models/query.py", line 411 in get
  File ".../lib/python3.6/site-packages/django/db/models/base.py", line 627 in refresh_from_db
  File ".../lib/python3.6/site-packages/django/db/models/query_utils.py", line 139 in __get__
  File ".../lib/python3.6/site-packages/model_utils/tracker.py", line 100 in get_field_value
  File ".../lib/python3.6/site-packages/model_utils/tracker.py", line 126 in <dictcomp>
  File ".../lib/python3.6/site-packages/model_utils/tracker.py", line 126 in current
  File ".../lib/python3.6/site-packages/model_utils/tracker.py", line 106 in set_saved_fields
  File ".../lib/python3.6/site-packages/model_utils/tracker.py", line 232 in initialize_tracker
  File ".../lib/python3.6/site-packages/django/dispatch/dispatcher.py", line 175 in <listcomp>
  File ".../lib/python3.6/site-packages/django/dispatch/dispatcher.py", line 175 in send
  File ".../lib/python3.6/site-packages/django/db/models/base.py", line 502 in __init__
  File ".../lib/python3.6/site-packages/django/db/models/base.py", line 512 in from_db
  File ".../lib/python3.6/site-packages/django/db/models/query.py", line 75 in __iter__
  File ".../lib/python3.6/site-packages/django/db/models/query.py", line 1261 in _fetch_all
  File ".../lib/python3.6/site-packages/django/db/models/query.py", line 258 in __len__
  File ".../lib/python3.6/site-packages/django/db/models/query.py", line 411 in get
  File ".../lib/python3.6/site-packages/django/db/models/base.py", line 627 in refresh_from_db

wagmiwiz avatar Mar 02 '20 22:03 wagmiwiz

After some digging it appears this happens if you have a tracker on a ForeignKey field but you don't use the id. Django 3 then tries to initialise the field and you get into the infinite loop.

e.g. FieldTracker(fields="some_foreign_key_field") gets into the above state but FieldTracker(fields="some_foreign_key_field_id") does not

wagmiwiz avatar Mar 03 '20 09:03 wagmiwiz

I noticed this in Django 4 as well

jottenlips avatar Apr 26 '22 20:04 jottenlips

We narrowed field tracker down to only the fk field we needed to track with _id at the end of the field name.

jottenlips avatar Apr 29 '22 13:04 jottenlips