2013-07-12 38 views
7

Tôi có vấn đề lạ này với một trong các mô hình Django của tôi và tôi đã có thể khắc phục nó nhưng không hiểu điều gì đang xảy ra.Độ sâu đệ quy tối đa vượt quá trên mô hình Django khi tạo

Đây là những mô hình:

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

Bất cứ khi nào tôi thực hiện một (trống) đối tượng Team mới và muốn có được players từ nó, tôi nhận được một RuntimeError: maximum recursion depth exceeded. Ví dụ:

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

Tại sao điều này xảy ra? Tôi đã có thể sửa chữa nó bằng cách kiểm tra cho pk và chỉ tạo ra tên sau đó, nhưng những gì tôi nghĩ rằng nó nên làm việc theo cách là trở về chỉ có tên bởi vì ", ".join... sẽ là một danh sách sản phẩm nào. Thay vào đó, một số đệ quy xảy ra mà tôi không hiểu.

Trả lời

15

Sự cố là bạn không thể truy cập trường team.players khi phiên bản Team chưa được lưu vào cơ sở dữ liệu. Việc cố gắng thực hiện điều này sẽ tăng một số ValueError.

Tuy nhiên, trong khi cố gắng tăng số này ValueError, mã sẽ cố gắng để có được một đại diện của đối tượng team của bạn gián tiếp sẽ gọi unicode(team). Điều này sẽ cố gắng truy cập self.players, mà sẽ cố gắng để nâng cao ValueError trước khi người đầu tiên được nâng lên. Điều này tiếp tục cho đến khi đạt được độ sâu đệ quy tối đa, nhưng vẫn không có số ValueError được ném. Do đó, bạn sẽ chỉ thấy số RuntimeError.

Cùng sẽ (nên?) Xảy ra nếu bạn đã làm một trong hai điều sau đây:

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

Tốt giải thích về lỗi. – Brandon

+2

Truy cập mối quan hệ nhiều-nhiều trước khi cá thể được lưu sẽ tăng 'ValueError' và dẫn đến kịch bản được mô tả. Nếu cá thể được lưu (và có một khóa chính) thì mối quan hệ sẽ là một danh sách trống. – AndrewS

+0

@AndrewS Bạn nói đúng, đã cập nhật câu trả lời của tôi. Cảm ơn vì đã chú ý! – knbk

Các vấn đề liên quan