python中父子关系的动态树,其中数据与节点相关联

时间:2018-12-08 16:42:23

标签: python tree nested defaultdict

这是一个严格的学术问题,经过一番混乱-但基本上我想知道如果我从父子关系开始(django模型)如何制作reddit风格的嵌套评论系统

鉴于每个记录的父级以及与该记录相关联的一些数据的知识,如何创建任意深度的树结构,其中树中的每个节点(记录)不仅包含有关其与其他节点的关系的信息记录(由于在树中的位置),但也有与其关联的数据

class Record(models.Model):
    name = models.CharField(max_length=100, null=True, blank=True)
    parent = models.ForeignKey('Record', verbose_name='Hierarchical Parent', on_delete=models.CASCADE, null=True, blank=True)
    data = models.TextField()
    generation = models.IntegerField()

第一个问题是获取父子关系(尚未担心将数据与父关系相关)。

这个人Django how to make ul li hierachy from a self reference model完成了将类似的数据结构转换为嵌套无序html列表的工作,我也尝试过,效果很好。

但是我想要一个可以使用的数据结构,例如字典之类的东西。

最初,当我开始研究此问题时,我并没有考虑使用Reddit式评论,而是实际上正在将hierarchical db(这很久以前很流行)移到了django中应用程序中,我的Django“记录”表代表了层次关系:

Name   |  Parent
----------------
Account | None
Loan  | Account
Escrow | Loan
Person | Account
AccHx | Account
LoanHx | Loan

我想要类似的东西

{'Account':
    {'Loan':
        {'LoanHx':{},
         'Escrow':{}
        },
     'Person':{},
     'AccHx':{}
     }
}

并且能够使用defaultdict集合来做到这一点(很多HN发布了解决方案的灵感,例如How do I build a tree dynamically in Python

我的解决方案:

def add_element(root, path, data):
    if len(path) == 1:
        root[path[0]] = data
    else:
        add_element(root[path[0]], path[1:], data)

import collections
tree = lambda: collections.defaultdict(tree)
root = tree()
# add_element(root, ['toplevel', 'secondlevel', 'thirdlevel'], 1)
# add_element(root, ['toplevel', 'anotherlevel'], 2)

selected_records = Record.objects.all()[0:5]

#I have a generation field
for sr in selected_records:
    if sr.generation == 0:
        add_element(root, [sr.name], {})#sr.data)
    elif sr.generation == 1:
        add_element(root, [sr.parent.name, sr.name], {})#sr.data)
    elif sr.generation == 2:
        add_element(root, [sr.parent.parent.name, sr.parent.name, sr.name], {})#sr.data)
    elif sr.generation == 3:
        add_element(root, [sr.parent.parent.parent.name,
                           sr.parent.parent.name, sr.parent.name, sr.name], {})#sr.data)

因此,假设我有sr.data(即,如果我正在构建嵌套评论系统,则为评论内容)作为我的数据参数进入递归add_element(root,path,data)函数,然后在下一个递归中会收到TypeError-'str'不支持数据分配。因此,我将数据参数(新节点)设置为字典,以便可以继续递归。这样就成功创建了多级dict结构,如上所示。

但是如果我想要类似的东西怎么办?

{'Account':
    {'fields':['id','name',....],
     'children':
               {'Loan':
                    {'fields':['id','name',....],
                     'children':
                            {'LoanHx':{'fields':['id','name',....],
                     'children':{}},
 ....

我该如何更改add_element递归函数以适应呢?现在我已经把所有内容都写完了,我想我有个主意。

0 个答案:

没有答案