Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

maximum recursion depth exceeded on Django model when creating

I have this strange problem with one of my Django models and I was able to fix it but don't understand what is happening.

These are the models:

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

Whenever I make a new (empty) Team object and want to get players from it, I got a RuntimeError: maximum recursion depth exceeded. For example:

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

Why is this happening? I was able to fix it by checking for pk and only generate the name then, but what I think it should work the way is returning only the name because ", ".join... would be an empty list. Instead, some recursion occurs which I don't understand.

like image 829
kissgyorgy Avatar asked Jul 12 '13 10:07

kissgyorgy


People also ask

How do you fix maximum recursion depth exceeded?

The “maximum recursion depth exceeded in comparison” error is raised when you try to execute a function that exceeds Python's built in recursion limit. You can fix this error by rewriting your program to use an iterative approach or by increasing the recursion limit in Python.

How do I fix maximum recursion depth exceeded in comparison Python?

Conclusion. The recursion depth limit in Python is by default 1000 . You can change it using sys. setrecursionlimit() function.

What is recursion error in Django?

As the name suggests, Recursionerror may occur when we are dealing with recursive functions. When we run the recursion function for a large number of times, recursion error is thrown. Python has a limit on the number of times a recursive function can call itself.

How do you stop recursion errors in Python?

Try increasing the recursion limit ( sys. setrecursionlimit ) or re-writing your code without recursion. Return the current value of the recursion limit, the maximum depth of the Python interpreter stack. This limit prevents infinite recursion from causing an overflow of the C stack and crashing Python.


1 Answers

The problem is that you can't access the team.players field when the Team instance is not yet saved to the database. Trying to do this will raise a ValueError.

However, while trying to raise this ValueError, the code will try to get a representation of your team object which will indirectly call unicode(team). This will try to access self.players, which will try to raise another ValueError before the first one is raised. This goes on until the maximum recursion depth is reached, but there is still no ValueError thrown. Therefore, you'll only see the RuntimeError.

The same would (should?) happen if you did either of the following:

>>> team
>>> repr(team)
>>> unicode(team)
like image 178
knbk Avatar answered Dec 20 '22 14:12

knbk