Django MPTT以递归方式获取子项

时间:2018-04-06 10:50:54

标签: python django django-registration django-mptt

我在models.py

中获得了此代码
class Member(MPTTModel):
    parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True)
    name = models.CharField(max_length=120)

我正在使用Django和DRF。

当我访问http://localhost:8000/api/members/1/时,我得到类似的内容:

{
    "name": "Test Parent",
    "parent": null
}

这很好。但是我想要一些东西,当我访问http://localhost:8000/api/members/1/children时,我应该得到类似

的东西
{
    "name": "Test Parent",
    "parent": null,
    "children": [
        {
            "name": "Child 1"
        },
        {
            "name": "Child 2",
            "children": [
                {
                    "name": "Child 2.1", 
                    "children": [
                        {
                            "name": "Child 2.1.1"
                        }
                        .....
                    ]
                }
            ]
        }I got this code inside `models.py`


class Member(MPTTModel):
    parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True)
    name = models.CharField(max_length=120)

我正在使用Django和DRF。

当我访问http://localhost:8000/api/members/1/时,我得到类似的内容:

{
    "name": "Test Parent",
    "parent": null
}

这很好。但是我想要一些东西,当我访问http://localhost:8000/api/members/1/children时,我应该得到类似

的东西
{
    "name": "Test Parent",
    "parent": null,
    "children": [
        {
            "name": "Child 1"
        },
        {
            "name": "Child 2",
            "children": [
                {
                    "name": "Child 2.1", 
                    "children": [
                        {
                            "name": "Child 2.1.1"
                        }
                        .....
                    ]
                }
            ]
        }
    ]
}

如何实现上述目标?

我使用get_descendants(),但它不是我想要的那种

[
    {
        "id": 1,
        "name": "Test Parent",
        "parent": null
    },
    {
        "id": 2,
        "name": "Child 1",
        "parent": 1
    },
    {
        "id": 3,
        "name": "Child 2",
        "parent": 1
    },
    {
        "name": "Child 1.1",
        "parent": 2
    },
    {
        "name": "Child 2.1",
        "parent": 3
    }
]

这是我的views.py

class MemberViewSet(viewsets.ModelViewSet):
    queryset = Member.objects.all()
    serializer_class = MemberSerializer

    @action(detail=True)
    def children(self, request, pk=None):
        parent = Member.objects.get(pk=pk)
        child = parent.get_descendants(include_self=False)

        serializer = self.get_serializer(child, many=True)

        return Response(serializer.data)

1 个答案:

答案 0 :(得分:0)

对于尽可能少的数据,您可以使用一个小的递归函数:

def get_children(data, item_id):
    children = [i for i in data if i["parent"] == item_id]

    for child in children:
        try:
            child["children"] = get_children(data, child["id"])
        except KeyError:
            pass
    return children

out = data[0]
out["children"] = get_children(data, out["id"])

请注意,这不会很好地适应大量数据!