1

enter image description here

In this tree I want to do a query so that only the first generation of the red circle is extracted. But the condition is that the value of each circle must be greater than zero, ie the green circles:

enter image description here

Serializers:

class CircleBaseSerializer(serializers.ModelSerializer):
    class Meta:
        model = Circle
        fields = ('id', 'value')


class CircleChildrenSerializer(CircleBaseSerializer):
    class Meta(CircleBaseSerializer.Meta):
        pass

class CircleParentSerializer(CircleBaseSerializer):
    children = CircleChildrenSerializer(many=True)
    class Meta(CircleBaseSerializer.Meta):
       pass

View:

class CircleViewSet(ReadOnlyModelViewSet):
    serializer_class = CircleParentSerializer
    queryset = Circle.objects.all()
    def get_queryset(self):
        id = self.kwargs["id"]
        u=Circle.objects.get(pk=id)

Certainly result is [5(1,0,3)] that is not desirable. How can I do this query?

mrbf
  • 512
  • 1
  • 7
  • 23
  • (Bad implementation) You do not treat MPTT like this in the serializer. Moreover, I would strongly suggest you to use django-mptt within your model and make the logic there. In addition, if you read the `django-mptt` documentation you will find a lot of functions that help with this issues. – Elias Prado Oct 27 '22 at 00:04

1 Answers1

0

Maybe my answer is late but will be useful for others. There are many ways to achieve what you are asking, the simple one:

models.py


from django.db import models
from mptt import models as MpttModels


class Circle(MpttModels.MPTTModel):

     parent = MpttModels.TreeForeignKey(
        'self',
        null=True,
        blank=True,
        on_delete=models.CASCADE,
        related_name='leaf_nodes'
    )
    value = models.SmallIntegerField()

    def __str__(self):
        """String representation of model objects"""

        full_path = [self.value]
        next_category = self.parent
        while next_category is not None:
            full_path.append(next_category.value)
            next_category = next_category.parent

        return ' -> '.join(full_path[::-1])

serializers.py


from rest_framework import serializers
from your_api.models import Circle

class CircleSerializer(serializers.ModelSerializer):
    """Serialize class of Circle model"""
    
    class Meta:
        model = Circle
        fields = ['id', 'value', 'leaf_nodes']

    leaf_nodes = serializers.SerializerMethodField()

    def get_leaf_nodes(self, instance):
        """Return all children of instance when condition is true"""

        # You can use get_children() method of ModelSerializer
        # (or you can use related_name of ForeignKey) to serialize
        # reverse relation of ForeignKey field.
    
        return CircleSerializer(
            instance.get_children().filter(value__gt=0),
            many=True
        ).data

This serialize class will return parent node (the one you select in view class using queryset for specific 'id') and its children those have value greater than zero.

Wadhah Sky
  • 90
  • 1
  • 8