如何在Django REST中序列化层次关系

时间:2014-01-14 11:21:19

标签: python django serialization django-rest-framework django-mptt

我有一个使用django-mptt分层的Django模型,它看起来像:

class UOMCategory(MPTTModel, BaseModel):
    """
        This represents categories of different unit of measurements.
    """
    name = models.CharField(max_length=50, unique=True)
    description = models.CharField(max_length=50, unique=True)
    parent = TreeForeignKey('self', null=True, blank=True, related_name='%(app_label)s_%(class)s_sub_uom_categories')

现在的问题是我使用Django REST Framework创建了一个REST API;如何确保父字段返回序列化数据?

以下是Model Serializer:

class UOMCategorySerializer(BaseModelSerializer):
    """
    REST API Serializer for UOMCategory model
    """
    class Meta:
        model = UOMCategory

2 个答案:

答案 0 :(得分:8)

在DRF中,您可以将序列化程序用作另一个序列化程序中的字段。但是,递归是不可能的。

汤姆克里斯蒂在另一个问题(Django rest framework nested self-referential objects)上发布了一个解决方案。他的解决方案也适用于你的问题。

在您的UOMCategorySerializer.Meta类中指定要使用的字段,还列出其中的父字段和/或子字段。然后你使用Tom Christies解决方案。

在你的情况下,这将给出:

class UOMCategorySerializer(ModelSerializer):
    class Meta:
        model = UOMCategory
        fields = ('name', 'description', 'parent', 'children')

Tom Christies解决方案:通过指定父母和/或孩子使用哪个字段,您可以避免使用太多(可能无限的)递归:

UOMCategorySerializer.base_fields['parent'] = UOMCategorySerializer()
UOMCategorySerializer.base_fields['children'] = UOMCategorySerializer(many=True)

以上情况适用于类似情况。

答案 1 :(得分:0)

使用 MPTT 缓存和 DRF 序列化程序的简单 DRF API 视图。

from rest_framework import serializers
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response

from events.models import Category


class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = (
            "name",
            "slug",
        )


class CategoryTreeView(GenericAPIView):
    serializer_class = CategorySerializer

    def get(self, request, *args, **kwargs):
        root_nodes = Category.objects.all().get_cached_trees()

        data = []
        for n in root_nodes:
            data.append(self.recursive_node_to_dict(n))

        return Response(data)

    def recursive_node_to_dict(self, node):
        result = self.get_serializer(instance=node).data
        children = [self.recursive_node_to_dict(c) for c in node.get_children()]
        if children:
            result["children"] = children
        return result