#31435: RecursionError when deleting a model with one to many relationship
-------------------------------------+-------------------------------------
               Reporter:  Fabian     |          Owner:  nobody
  Allendorf                          |
                   Type:  Bug        |         Status:  new
              Component:  Database   |        Version:  3.0
  layer (models, ORM)                |       Keywords:
               Severity:  Normal     |  
delete,model,recursion,stack,overflow,reference,foreign,key,one,to,many
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 This issue appeared with upgrade from Django 2 to Django 3.0. I double
 checked and it definitely works with version <3.0.

 There is a model with a duration field and the "__init__" method is
 overridden to save "old" values of this duration field.

 {{{
 class TimeSeries(models.Model):
   frequency = models.DurationField()
   def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
         self._old_frequency = self.frequency
 }}}

 Another model extends this "TimeSeries" model and has a foreign key
 reference to the model which I tried to delete.

 {{{
 class RefModel(TimeSeries):
   main_model = models.ForeignKey(
     MainModel, on_delete=models.CASCADE, related_name="refs"
   )

 class MainModel(models.Model):
   pass
 }}}

 So I created an instance of "MainModel" "main_a" and added some "RefModel"
 instances with relationhip to "main_a".
 When I call "main_a.delete()" it ends up in a stack overflow with the
 following stacktrace:

 {{{
 Traceback (most recent call last):
   File "<input>", line 1, in <module>
   File "/lib/python3.8/site-packages/django/db/models/base.py", line 937,
 in delete
     collector.collect([self], keep_parents=keep_parents)
   File "/lib/python3.8/site-packages/django/db/models/deletion.py", line
 244, in collect
     if sub_objs:
   File "/lib/python3.8/site-packages/django/db/models/query.py", line 280,
 in __bool__
     self._fetch_all()
   File "/lib/python3.8/site-packages/django/db/models/query.py", line
 1261, in _fetch_all
     self._result_cache = list(self._iterable_class(self))
   File "/lib/python3.8/site-packages/django/db/models/query.py", line 75,
 in __iter__
     obj = model_cls.from_db(db, init_list,
 row[model_fields_start:model_fields_end])
   File "/lib/python3.8/site-packages/django/db/models/base.py", line 512,
 in from_db
     new = cls(*values)
   File "/lib/python3.8/site-packages/django_timeseries/models.py", line
 27, in __init__
     self._old_frequency = self.frequency
   File "/webserver/business_rules/thread_safe_model_patcher.py", line 51,
 in _patched_get_attribute
     return Model.get(model_self, item)
   File "/lib/python3.8/site-packages/django/db/models/query_utils.py",
 line 139, in __get__
     instance.refresh_from_db(fields=[field_name])
   File "/lib/python3.8/site-packages/django/db/models/base.py", line 627,
 in refresh_from_db
     db_instance = db_instance_qs.get()
   File "/lib/python3.8/site-packages/django/db/models/query.py", line 411,
 in get
     num = len(clone)
   File "/lib/python3.8/site-packages/django/db/models/query.py", line 258,
 in __len__
     self._fetch_all()
   File "/lib/python3.8/site-packages/django/db/models/query.py", line
 1261, in _fetch_all
 <--- Stacktrace repeats itself from here on --->
 }}}

 "django_timeseries" is a custom package which defines the "TimeSeries"
 class.
 "thread_safe_model_patcher.py" monkeypatches the "Model" class. It has no
 effect on whether the error happens. I removed the this patch and it still
 errors.

 It seems to me that deleting "main_a" deletes all "RefModel" instances
 related to it (like it should) but while doing this, it gets stuck
 initializing the super class "TimeSeries" because the "__init__" accesses
 the "frequency" field.

-- 
Ticket URL: <https://code.djangoproject.com/ticket/31435>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/058.0c99a5ec14f366e1fb1de96f667740bb%40djangoproject.com.

Reply via email to