【问题标题】:maximum recursion depth exceeded on Django model when creating创建时超出 Django 模型的最大递归深度
【发布时间】:2013-07-10 21:43:00
【问题描述】:

我的一个 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... 将是一个空列表。相反,会发生一些我不理解的递归。

【问题讨论】:

    标签: django recursion model django-orm


    【解决方案1】:

    问题是当Team 实例尚未保存到数据库时,您无法访问team.players 字段。尝试这样做会引发ValueError

    但是,在尝试引发此ValueError 时,代码将尝试获取您的team 对象的表示,该对象将间接调用unicode(team)。这将尝试访问self.players,它将尝试在第一个ValueError 引发之前引发另一个ValueError。这一直持续到达到最大递归深度,但仍然没有抛出ValueError。因此,您只会看到RuntimeError

    如果您执行以下任一操作,同样会(应该?)发生:

    >>> team
    >>> repr(team)
    >>> unicode(team)
    

    【讨论】:

    • 在保存实例之前访问多对多关系将引发ValueError 并导致所描述的场景。如果实例已保存(并且具有主键),则该关系将是一个空列表。
    • @AndrewS 你是对的,更新了我的答案。感谢您的关注!
    猜你喜欢
    • 1970-01-01
    • 2017-08-09
    • 2011-03-31
    • 1970-01-01
    • 2013-02-20
    • 1970-01-01
    • 1970-01-01
    • 2013-12-01
    相关资源
    最近更新 更多