Opened 18 years ago
Closed 17 years ago
#3288 closed defect (fixed)
ForeignKey to 'self' and select_related() = infinite recursion
Reported by: | Owned by: | Philippe Raoult | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | major | Keywords: | qs-rf-fixed |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | yes |
Easy pickings: | no | UI/UX: | no |
Description
Maybe it's a variant of #3045 bug.
The [simplified] case is
class Foo(models.Model): parent = models.ForeignKey('self') class Meta: db_table = 'foos' foo = Foo.objects.select_related().get(pk=1)
That leads to infinite recursion in django.db.models.query.fill_table_cache. The bottom of the stack trace is:
........ many many lines ............ File "/home/maxim/dproject/django/db/models/query.py", line 684, in fill_table_cache fill_table_cache(f.rel.to._meta, select, tables, where, db_table, cache_tables_seen) File "/home/maxim/dproject/django/db/models/query.py", line 684, in fill_table_cache fill_table_cache(f.rel.to._meta, select, tables, where, db_table, cache_tables_seen) File "/home/maxim/dproject/django/db/models/query.py", line 681, in fill_table_cache where.append('%s.%s = %s.%s' % \ File "/home/maxim/dproject/django/db/models/fields/related.py", line 737, in get_related_field return self.to._meta.get_field(self.field_name) File "/home/maxim/dproject/django/db/models/options.py", line 98, in get_field if f.name == name: RuntimeError: maximum recursion depth exceeded in cmp
Attachments (2)
Change History (16)
comment:1 by , 18 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:2 by , 18 years ago
this is a special case of bug #2885, which I've marked as duplicate of this one.
comment:3 by , 17 years ago
Has patch: | set |
---|---|
Keywords: | qs-rf added |
Owner: | changed from | to
Status: | new → assigned |
Version: | → SVN |
comment:4 by , 17 years ago
although this is marked qs-rf, it is a very simple patch and it can also be applied to 96! The regression test should go in the trunk so qs-rf will be tested against it whenever it is merged.
comment:6 by , 17 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
It should be noted that the attached patches also fix #2549 and #3045 at the same time. The regression tests cover both their cases (FK cycle) and ours (FK to self). I'm adding patches even though this is marked qs-rf because this is a nasty bug and 0.96 users might want to have it. Also we might as well put the reg tests in trunk so this issue isn't replicated by qs-rf.
comment:7 by , 17 years ago
Patch needs improvement: | set |
---|
I applied 3288_96.diff with no effect. My model is:
class ProjectImage(models.Model):
project = models.ForeignKey("Project", null=True, edit_inline=True, core=True)
title = models.CharField(maxlength=50, blank=True)
description = models.TextField(blank=True)
image = models.ImageField(upload_to='project', height_field="100", width_field="100", blank=False)
faqs = models.ManyToManyField(Faq, blank=True)
categories = models.ManyToManyField(Category)
class Project(models.Model):
title = models.CharField(maxlength=50)
description = models.TextField()
pub_date = models.DateTimeField(auto_now_add=True)
icon = models.ForeignKey(ProjectImage, edit_inline=True, core=True, related_name='icon')
parts = models.ManyToManyField(Part)
cars = models.ManyToManyField(Car)
faqs = models.ManyToManyField(Faq, blank=True)
The patch does not break any functionality but I still encounter the same error.
Exception Type: RuntimeError
Exception Value: maximum recursion depth exceeded in cmp
Exception Location: /home/patrickm/lib/python2.4/django/db/models/fields/init.py in get_follow, line 328
comment:8 by , 17 years ago
Adding edit_inline=True seems to break the patch.
In above example make error go away by changing:
project = models.ForeignKey("Project", null=True, edit_inline=True, core=True)
to:
project = models.ForeignKey("Project", null=True, core=True)
That resolved the issue if it persists after patch is applied.
comment:9 by , 17 years ago
comment:10 by , 17 years ago
Keywords: | qs-rf-fixed added; qs-rf removed |
---|---|
Triage Stage: | Ready for checkin → Accepted |
comment:11 by , 17 years ago
Dunno if the same bug but I got something similar with this:
class Test(models.Model): recursion_loop = models.ForeignKey('self',edit_inline=models.TABULAR)
this is the output
File "/home/visi/djtrunk/django/db/models/related.py", line 99, in get_follow return self.opts.get_follow(over) File "/home/visi/djtrunk/django/db/models/options.py", line 177, in get_follow fol = f.get_follow(child_override) File "/home/visi/djtrunk/django/db/models/related.py", line 99, in get_follow return self.opts.get_follow(over) File "/home/visi/djtrunk/django/db/models/options.py", line 177, in get_follow fol = f.get_follow(child_override) File "/home/visi/djtrunk/django/db/models/related.py", line 99, in get_follow return self.opts.get_follow(over) File "/home/visi/djtrunk/django/db/models/options.py", line 177, in get_follow fol = f.get_follow(child_override) File "/home/visi/djtrunk/django/db/models/related.py", line 99, in get_follow return self.opts.get_follow(over) File "/home/visi/djtrunk/django/db/models/options.py", line 177, in get_follow fol = f.get_follow(child_override) File "/home/visi/djtrunk/django/db/models/fields/__init__.py", line 372, in get_follow if override != None: RuntimeError: maximum recursion depth exceeded in cmp
comment:13 by , 17 years ago
I wanted to note that this error popups for OneToOneFields: location_category = models.OneToOneField('self', blank=True)
comment:14 by , 17 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
(In [7477]) Merged the queryset-refactor branch into trunk.
This is a big internal change, but mostly backwards compatible with existing
code. Also adds a couple of new features.
Fixed #245, #1050, #1656, #1801, #2076, #2091, #2150, #2253, #2306, #2400, #2430, #2482, #2496, #2676, #2737, #2874, #2902, #2939, #3037, #3141, #3288, #3440, #3592, #3739, #4088, #4260, #4289, #4306, #4358, #4464, #4510, #4858, #5012, #5020, #5261, #5295, #5321, #5324, #5325, #5555, #5707, #5796, #5817, #5987, #6018, #6074, #6088, #6154, #6177, #6180, #6203, #6658
I could reproduce the bug. The db_table setting is not necessary. Funny, it really works (as reported) without any data in the table for foo.
I'm closing #3045 in favour of this ticket since it appears to be the same bug, and #3288 is a lot clearer. But if we have a patch for #3288, please test it also for #3045! The conditions for #3045 are a bit different and more complicated.