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