2013-07-12 46 views
7

我的Django模型中有一个奇怪的问题,我可以修复它,但不明白发生了什么。创建Django模型时超出最大递归深度

这些机型:

class Player(models.Model): 
    facebook_name = models.CharField(max_length=100) 
    nickname = models.CharField(max_length=40, blank=True) 

    def __unicode__(self): 
     return self.nickname if self.nickname else self.facebook_name 


class Team(models.Model): 
    name = models.CharField(max_length=50, blank=True) 
    players = models.ManyToManyField(Player) 

    def __unicode__(self): 
     name = '(' + self.name + ') ' if self.name else '' 
     return name + ", ".join([unicode(player) for player in self.players.all()]) 

每当我提出一个新的(空)Team对象,并希望从它那里得到players,我得到了一个RuntimeError: maximum recursion depth exceeded。 例如:

>>> team = Team() 
>>> team.players 
    Traceback (most recent call last): 
    File "<console>", line 1, in <module> 
    File "/Users/walkman/Projects/fociadmin/venv/lib/python2.7/site-packages/django/db/models/fields/related.py", line 897, in __get__ 
    through=self.field.rel.through, 
    File "/Users/walkman/Projects/fociadmin/venv/lib/python2.7/site-packages/django/db/models/fields/related.py", line 586, in __init__ 
    (instance, source_field_name)) 
    File "/Users/walkman/Projects/fociadmin/venv/lib/python2.7/site-packages/django/db/models/base.py", line 421, in __repr__ 
    u = six.text_type(self) 
    File "/Users/walkman/Projects/fociadmin/fociadmin/models.py", line 69, in __unicode__ 
    return name + ", ".join([unicode(player) for player in self.players.all()]) 
    File "/Users/walkman/Projects/fociadmin/venv/lib/python2.7/site-packages/django/db/models/fields/related.py", line 897, in __get__ 
    through=self.field.rel.through, 
    File "/Users/walkman/Projects/fociadmin/venv/lib/python2.7/site-packages/django/db/models/fields/related.py", line 586, in __init__ 
    (instance, source_field_name)) 
    File "/Users/walkman/Projects/fociadmin/venv/lib/python2.7/site-packages/django/db/models/base.py", line 421, in __repr__ 
    u = six.text_type(self) 
    File "/Users/walkman/Projects/fociadmin/fociadmin/models.py", line 69, in __unicode__ 
    return name + ", ".join([unicode(player) for player in self.players.all()]) 
... 

这究竟是为什么?我能够通过检查pk来修复它,然后只生成名称,但我认为它应该按照这种方式返回名称,因为", ".join...应该是一个空列表。相反,发生了一些我不明白的递归。

回答

15

问题是,当Team实例尚未保存到数据库时,您无法访问team.players字段。试图做到这一点将产生ValueError

然而,在努力提高这ValueError,代码会试图让你team对象的表示,这将间接调用unicode(team)。这将尝试访问self.players,在第一次提出之前,它将尝试再次提出ValueError。这一直持续到达到最大递归深度,但仍然没有抛出ValueError。因此,您只会看到RuntimeError

同样会如果你做下面的任一(应该?)发生:

>>> team 
>>> repr(team) 
>>> unicode(team) 
+0

错误很好的解释。 – Brandon

+2

在实例保存之前访问多对多关系会引发一个ValueError并导致所描述的场景。如果实例被保存(并且具有主键),那么该关系将是空列表。 – AndrewS

+0

@AndrewS你说得对,更新了我的答案。感谢您的注意! – knbk

相关问题