Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django .only() causing maximum recursion depth exceeded error?

I was using Django's .only() construct to query only the columns I need.

ex.

Trainer.objects.filter(id__in=ids).only('id', 'lives')

Here is a quick example I wrote to reproduce this:

class BaseTrainer(models.Model):

    mode = models.IntegerField(help_text="An integer")

    def __init__(self, *args, **kwargs):
    super(BaseTrainer, self).__init__(*args, **kwargs)
    self._prev_mode = self.mode


class Trainer(BaseTrainer):

    name = models.CharField(max_length=100, help_text="Name of the pokemon")
    trainer_id = models.CharField(max_length=10, help_text="trainer id")
    badges = models.IntegerField(help_text="Power of the pokemon (HP)")
    lives = models.PositiveIntegerField(default=sys.maxsize)

    unique_together = ("name", "trainer_id")

    def __init__(self, *args, **kwargs):
        super(Trainer, self).__init__(*args, **kwargs)
        self._temp = self.lives

    @classmethod
    def test(cls):

        t = Trainer.objects.only('trainer_id').all()

        print(t)

I needed only id and name fields, that's certain. And what was the reason for maximum recursion depth exceeded?

like image 520
priyankvex Avatar asked Aug 07 '17 13:08

priyankvex


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 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.

How do I change the maximum recursion depth in Python?

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


1 Answers

It turned out that the reason for maximum recursion depth exceeded was because of inheriting from a model and constructor overriding.

As you can see in the code,

self._prev_mode = self.mode

we try to access mode in the constructor of the super model class. So, even if we don't need this field for our use, we still have to include this in .only() in every such call for this model.

But, according to docs, .only() should make another database query to get the field value in worst case, why recursion?

Well, note that this field was being accessed in the constructor of the parent model. And that was the catch. Each time, the value was couldn't be read in the constructor and thus was attempted to fetch from the database. That called the constructor again and the recursion cycle continued until the python stopped it.

Anyway, fixed this by adding the mode in the .only() call too.

Trainer.objects.filter(id__in=ids).only('id', 'name', 'mode')

like image 86
priyankvex Avatar answered Sep 18 '22 22:09

priyankvex