Django模型:根节点在未保存的节点中显示为子节点

2024-04-16 17:34:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图在django中建立一个树结构模型。这是我现有的简化版:

from django.db import models

class Node(models.Model):
    parent = models.ForeignKey("Node", null=True)
    name = models.CharField(max_length=20)

    def child_cnt(self):
        return self.node_set.count()

    def __unicode__(self):
        return self.name

到目前为止还不错。它起作用了。但如果我现在开始创建这样的层次结构:

^{pr2}$

那么根节点作为n内部的子节点是什么呢?我怎么才能避免呢?在

当我调用n.save()后,问题就消失了,但是在管理站点中看到一个以1的child_cnt初始化的节点有点讨厌。在


Tags: djangonamefrom模型selfnodechilddb
2条回答

好吧,经过一番研究,结果如下:

首先,请注意-在使用ForeignKey和递归关系时,应该使用'self'而不是类名: https://docs.djangoproject.com/en/dev/ref/models/fields/#django.db.models.ForeignKey

那么,外国的关键是一对一的关系。枚举父节点时枚举子节点是不正确的。。。 回到问题上来-当你呼叫node时_全部设置()-这似乎被执行为Node.objects.all(),这就是为什么它显示新创建的节点实例的项(不保存在数据库中)。事实上node.node_集不能在此处用于获取节点的foreignkey。为了使一个节点有多个子节点-必须使用ManyToManyField,例如:

children = models.ManyToManyField('self', null=True)

然后用以下方法调用它:

^{pr2}$

或者

node.children.count()

编辑

简要分析:

class A(model):
    parent = ForeignKey(B)

那么

a = A()
b = B()
b.parent_set.all() 

将返回所有以B为父级的A,或所有具有parent_id=B.id的A

a = A()
b = A()
b.parent_set.all() 

将返回所有以b(==A)作为父节点的A,在这种情况下,A.parent_id=b.id,但b.id为None(未保存),因此您将获得所有父节点(b)的parent_id=None。在

事实上,这种行为对于非递归关系也是一样的。在第一个示例中,使用parent=None保存A(),您将在b.parent中获得它_全部设置()所有未保存的B

我知道这听起来很疯狂,但我花了几分钟试图解决你的问题,但我尝试的任何尝试都没有奏效。 无论如何,对于树ForeignKey,我在网上找到了另一个解决方案,它是一个处理这类键的整个库,https://github.com/django-mptt/django-mptt 你可以试试,也许适合你。我不喜欢为这么小的事情增加一个库,但是我找不到更好的。在

另外,如果您不想导入整个库,您可以将treefoweKey带到代码中。在

相关问题 更多 >