Django

Code

Ticket #7107 (closed: fixed)

Opened 7 months ago

Last modified 5 months ago

ManyToMany self-referential models *need* a related_name

Reported by: tsouanas Assigned to: mtredinnick
Milestone: 1.0 Component: Uncategorized
Version: SVN Keywords: qsrf-cleanup manytomany, infinite loop
Cc: Triage Stage: Accepted
Has patch: 0 Needs documentation: 0
Needs tests: 0 Patch needs improvement: 0

Description

Without a related_name, self-referential ManyToMany? models seem cause an infinite loop when trying to insert new objects.

Attachments

Change History

04/28/08 09:44:51 changed by mtredinnick

  • needs_better_patch changed.
  • needs_tests changed.
  • needs_docs changed.

I cannot repeat this problem. Can you please provide a short example model and instructions for how to trigger the problem?

I've been using this model for testing and I can insert, query and remove things from the m2m field without any problems.

class M2MSelfRef(models.Model):
    name = models.CharField(max_length=10)
    similar = models.ManyToManyField('self')

    def __unicode__(self):
        return '%s - %s' % (self.name, ', '.join(self.similar.values_list('name', flat=True)))

04/28/08 11:26:41 changed by anonymous

Using this model, when I try to edit it from the admin interface (newforms-admin) without the related_name attribute, I get a

Infinite loop caused by ordering.

error.

(I also used to have an "order_with_respect_to = 'parents'" inside the Meta class but I removed it.)

class Topic(models.Model):
    topic = models.CharField(max_length=128)
    parents = models.ManyToManyField('self', related_name='topic_parents', null=True, blank=True)

    class Meta:
        ordering = ('topic',)

    def ancestors(self):
        if not self.parents:
            return [self]
        else:
            return sum([parent.ancestors() for parent in self.parents], [self])

    def subtopic_of(self, topic):
        return topic in self.ancestors()

    def related_with(self, topic):
        return self.subtopic_of(topic) or topic.subtopic_of(self)

06/10/08 11:00:34 changed by gav

  • keywords changed from manytomany, infinite loop to qsrf-cleanup manytomany, infinite loop.

06/16/08 12:10:45 changed by jacob

  • milestone set to 1.0.

06/26/08 00:42:55 changed by mtredinnick

  • version changed from SVN to newforms-admin.
  • component changed from Documentation to Uncategorized.

I'm going to reassign this to the newforms-admin branch, since it doesn't seem to be core-related. The normal core code will not be using parent anywhere in the ordering querying, since it's just not specified. If newforms-admin is somehow introducing an implicit ordering on that many-to-many relation, it needs to work out how it's going to avoid the infinite loop problem. I haven't looked at the newforms-admin code to see what's going on here, but, as indicated in the first comment, I can't repeat it with normal code on trunk.

So Brian or Karen ... any big ideas what's going on here?

06/26/08 01:56:29 changed by Karen Tracey <kmtracey@gmail.com>

  • version changed from newforms-admin to SVN.

I don't think the problem is in the admin. I can recreate the problem by just doing a Topic.objects.all() in a python shell with the given model. The problem seems to relate to having specified an ordering on a field that is identical except for case to the name of the Model. If I change the model name so that is different than the field name then the problem goes away. That is, given these models:

class Topic(models.Model):
    topic = models.CharField(max_length=128)
    parents = models.ManyToManyField('self', null=True, blank=True)

    class Meta:
        ordering = ('topic',)

class TopicModel(models.Model):
    topic = models.CharField(max_length=128)
    parents = models.ManyToManyField('self', null=True, blank=True)

    class Meta:
        ordering = ('topic',)

this is what I see:

Python 2.5.1 (r251:54863, Mar  7 2008, 04:10:12)
[GCC 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> import django
>>> django.get_version()
u'0.97-pre-SVN-7739'
>>> from m2m.models import Topic,TopicModel
>>> Topic.objects.all()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/homedir/django/trunk/django/db/models/query.py", line 129, in __repr__
    return repr(list(self))
  File "/homedir/django/trunk/django/db/models/query.py", line 141, in __len__
    self._result_cache.extend(list(self._iter))
  File "/homedir/django/trunk/django/db/models/query.py", line 248, in iterator
    for row in self.query.results_iter():
  File "/homedir/django/trunk/django/db/models/sql/query.py", line 200, in results_iter
    for rows in self.execute_sql(MULTI):
  File "/homedir/django/trunk/django/db/models/sql/query.py", line 1464, in execute_sql
    sql, params = self.as_sql()
  File "/homedir/django/trunk/django/db/models/sql/query.py", line 247, in as_sql
    ordering = self.get_ordering()
  File "/homedir/django/trunk/django/db/models/sql/query.py", line 583, in get_ordering
    self.model._meta, default_order=asc):
  File "/homedir/django/trunk/django/db/models/sql/query.py", line 627, in find_ordering_name
    order, already_seen))
  File "/homedir/django/trunk/django/db/models/sql/query.py", line 621, in find_ordering_name
    raise FieldError('Infinite loop caused by ordering.')
FieldError: Infinite loop caused by ordering.
>>> TopicModel.objects.all()
[]
>>>

06/26/08 02:03:21 changed by mtredinnick

  • owner changed from nobody to mtredinnick.
  • stage changed from Unreviewed to Accepted.

Right, my bad then. I'll fix it.

06/26/08 05:50:25 changed by mtredinnick

  • status changed from new to closed.
  • resolution set to fixed.

(In [7764]) Fixed the way symmetrical many-to-many relations are recorded in the Options class.

These types of relations don't have reverse accessor names, so that name can be used by a normal field on the model. Fixed #7107.


Add/Change #7107 (ManyToMany self-referential models *need* a related_name)




Change Properties
Action