2013-07-12 14 views
7

Ich habe dieses seltsame Problem mit einem meiner Django-Modelle und konnte es beheben, verstehe aber nicht, was passiert.Maximale Rekursionstiefe beim Erstellen des Django-Modells überschritten

Dies sind die Modelle:

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()]) 

Immer, wenn ich ein neues (leeres) Team Objekt machen und will players davon zu bekommen, ich bekam ein RuntimeError: maximum recursion depth exceeded. Zum Beispiel:

>>> 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()]) 
... 

Warum passiert das? Ich konnte es reparieren, indem ich nach pk prüfte und den Namen nur dann dann erzeugte, aber was ich denke, dass es den Weg arbeiten sollte, gibt nur den Namen zurück, weil ", ".join... eine leere Liste sein würde. Stattdessen tritt eine Rekursion auf, die ich nicht verstehe.

Antwort

15

Das Problem besteht darin, dass Sie nicht auf das Feld team.players zugreifen können, wenn die Team-Instanz noch nicht in der Datenbank gespeichert ist. Wenn Sie dies versuchen, wird eine ValueError ausgelöst.

Beim Versuch, diese ValueError zu erhöhen, wird der Code versuchen, eine Darstellung Ihres team Objekts zu erhalten, das indirekt unicode(team) aufrufen wird. Dies wird versuchen, auf zuzugreifen, die versuchen wird, einen weiteren ValueError zu erhöhen, bevor der erste ausgelöst wird. Dies geht so lange, bis die maximale Rekursionstiefe erreicht ist, aber es wird immer noch keine ValueError geworfen. Daher sehen Sie nur die RuntimeError.

Das gleiche würde (sollte?) Passieren, wenn Sie eine der folgenden tat:

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

Gute Erklärung des Fehlers. – Brandon

+2

Der Zugriff auf die Viele-zu-Viele-Beziehung vor dem Speichern der Instanz führt zu einem "ValueError" und führt zum beschriebenen Szenario. Wenn die Instanz gespeichert ist (und einen Primärschlüssel hat), wäre die Beziehung eine leere Liste. – AndrewS

+0

@Andrews Du hast Recht, habe meine Antwort aktualisiert. Danke fürs bemerken! – knbk

Verwandte Themen