Python – Django rest framework: Derived model serializer fields

Django rest framework: Derived model serializer fields… here is a solution to the problem.

Django rest framework: Derived model serializer fields

I’m building a tree-like hierarchical database system using the Django Rest Framework and django-polymorphic-tree. I have two models – BaseTreeNode and DescriptionNode (the latter is derived from BaseTreeNode). Specifically, here is my models.py:

class BaseTreeNode(PolymorphicMPTTModel):
    parent = PolymorphicTreeForeignKey('self', blank=True, null=True, related_name='children', verbose_name=_('parent'))
    title = models. CharField(_("Title"), max_length=200)

def __str__(self):
        return "{}>{}".format(self.parent, self.title)

class Meta(PolymorphicMPTTModel.Meta):
        verbose_name = _("Tree node")
        verbose_name_plural = _("Tree nodes")

# Derived model for the tree node:

class DescriptionNode(BaseTreeNode):
    description = models. CharField(_("Description"), max_length=200)

class Meta:
        verbose_name = _("Description node")
        verbose_name_plural = _("Description nodes")

Therefore, each title field (belonging to BaseTreeNode) has an associated description field (belonging to DescriptionNode).

Django Admin View

Now, all I want is JSON that returns a nested representation of the entire tree.
Currently, I only define a simple serializer with recursive fields.
My serializer .py

from rest_framework_recursive.fields import RecursiveField

class DescriptionNodeSerializer(serializers. ModelSerializer):
    class Meta:
        model = DescriptionNode
        fields = ('description',)

class BaseTreeNodeSerializer(serializers. ModelSerializer):
    subcategories = serializers. ListSerializer(source="children",child=RecursiveField())  
    class Meta:
        model = BaseTreeNode
        fields = ('id', 'title', 'subcategories')

This gave me (only for BaseTreeNodeSerializer):

[
  {
    "id": 1,
    "title": "Apple",
    "subcategories": [
      {
        "id": 2,
        "title": "Contact Person",
        "subcategories": []
      },
      {
        "id": 3,
        "title": "Sales Stage",
        "subcategories": [
          {
            "id": 4,
            "title": "Suspecting",
            "subcategories": [
              {
                "id": 5,
                "title": "Contact verification",
                "subcategories": []
              }
            ]
          },
          {
            "id": 6,
            "title": "Prospecting",
            "subcategories": [
              {
                "id": 7,
                "title": "Client Detail",
                "subcategories": []
              }
            ]
          }
        ]
      },
      {
        "id": 9,
        "title": "Medium",
        "subcategories": [
          {
            "id": 10,
            "title": "Status",
            "subcategories": []
          }
        ]
      },
      {
        "id": 13,
        "title": "Remainder",
        "subcategories": []
      }
    ]
  }
]

My question is, how is the hierarchy?
Something like this:

... {
                "id": 5,
                "title": "Contact verification",
                "description": "Verified"
                "subcategories": []
              } ...

Solution

The corresponding model is as follows:

class DescriptionNode(BaseTreeNode):
    basetreenode = models. OneToOneField(BaseTreeNode, related_name="base_tree")
    description = models. CharField(_("Description"), max_length=200)

class Meta:
        verbose_name = _("Description node")
        verbose_name_plural = _("Description nodes")

The serializers are as follows:

from rest_framework_recursive.fields import RecursiveField

class BaseTreeNodeSerializer(serializers. ModelSerializer):
    description = serializers. SerializerMethodField()
    subcategories = serializers. ListSerializer(source="children",child=RecursiveField())

class Meta:
        model = BaseTreeNode
        fields = ('id', 'title', 'description', 'subcategories')

def get_description(self, obj):
        return obj.base_tree.description #base_tree is related name of basetreenode field

Related Problems and Solutions