heywbj / django-rest-framework-recursive

Recursive Serialization for Django REST framework
ISC License
367 stars 39 forks source link

maximum recursion depth exceeded #25

Closed elcolie closed 6 years ago

elcolie commented 6 years ago

models.py

from django.db import models
from mptt.models import MPTTModel, TreeForeignKey

from poinkbackend.apps.menus.models import Menu

class Category(MPTTModel):
    name = models.CharField(max_length=50)
    parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True)
    menu = models.ForeignKey(Menu, related_name='categories', related_query_name='categories',
                             on_delete=models.SET_NULL, null=True, blank=True)

    class MPTTMeta:
        order_insertion_by = ['name']

    def __str__(self):
        return f'{self.name} {self.menu}'

Serializers.py

from rest_framework import serializers
from rest_framework_recursive.fields import RecursiveField

from poinkbackend.apps.categories.models import Category

class CategorySerializer(serializers.ModelSerializer):
    parent = RecursiveField(allow_null=True)

    class Meta:
        model = Category
        fields = [
            'id',
            'name',
            'parent',
            'menu',
        ]

viewsets.py

from rest_framework import viewsets

from poinkbackend.apps.categories.api.serializers import CategorySerializer
from poinkbackend.apps.categories.models import Category

class CategoryViewSet(viewsets.ModelViewSet):
    queryset = Category.objects.all()
    serializer_class = CategorySerializer

I got the error maximum recursion depth exceeded

Where am I wrong?

django==1.11.9
djangorestframework-jwt==1.11.0
djangorestframework-recursive==0.1.2
djangorestframework==3.7.7
django-mptt==0.9.0
elcolie commented 6 years ago

After 5 months I am totally forgot.

21

heywbj commented 6 years ago

I apologize for not seeing this earlier, but your problem is exactly the error -- you are exceeding the maximum recursion depth. You probably have a cycle in your data structure, so the recursion will proceed without end.

elcolie commented 6 years ago

Hi. Thanks for getting back to the issue. It should produce the error. Since it is recursive by nature. And eager loading is not a recommend practice. I re-design to let my serializer becomes lazy-loader. Let it read through node by node not.

from rest_framework import serializers

from poinkbackend.apps.categories.models import Category
from poinkbackend.apps.menus.api.serializers import MenuSerializer

class ChildCategorySerializer(serializers.ModelSerializer):
    """Design to let it be a shallow detail"""
    url = serializers.HyperlinkedIdentityField(view_name='api:category-detail')
    image = serializers.ImageField(read_only=True)
    small_thumbnail = serializers.ImageField(read_only=True)
    medium_thumbnail = serializers.ImageField(read_only=True)
    large_thumbnail = serializers.ImageField(read_only=True)

    class Meta:
        model = Category
        fields = [
            'url',
            'id',
            'name',
            'image',
            'small_thumbnail',
            'medium_thumbnail',
            'large_thumbnail',
        ]

class CategoryTreeSerializer(serializers.ModelSerializer):
    ...
    children = ChildCategorySerializer(many=True)
    parent = ChildCategorySerializer()

    class Meta:
        model = Category
        fields = [
            ...
            'parent',
            'children',
        ]