Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django模型:根节点在未保存的节点中显示为子节点_Python_Django_Django Models - Fatal编程技术网

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

Python Django模型:根节点在未保存的节点中显示为子节点,python,django,django-models,Python,Django,Django Models,我试图在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()

我试图在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
到目前为止还不错。它起作用了。但如果我现在开始创建这样的层次结构:

from ....models import Node
root = Node()
root.name = "ROOT"
root.parent = None
root.save()

n = Node()
print n.child_cnt()
>> 1
print n.node_set.all()
[<Node: ROOT>]
从…模型导入节点
根=节点()
root.name=“root”
root.parent=None
root.save()
n=节点()
印刷品,印刷品
>> 1
打印n.node_set.all()
[]
那么根节点作为
n
中的子节点做什么呢?我怎样才能避免呢


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

我知道这听起来很疯狂,但我花了几分钟试图解决您的问题,但我尝试的任何尝试都没有成功。 总之,对于Tree ForeignKey,我在网上找到了另一个解决方案,那就是一个完整的库来处理这种类型的密钥, 你可以试试,它可能适合你。我讨厌为这么小的事情添加一个库,但是我找不到更好的


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

好的,经过一些研究-以下是结果:

首先,请注意-当使用ForeignKey与递归关系时,应使用“self”而不是类名:

那么-外键就是一对一的关系。枚举其父节点时枚举节点子节点是不正确的。。。 回到问题上-当调用node_set.all()时-它似乎是作为node.objects.all()执行的,这就是为什么它显示新创建的节点实例的项(未保存在DB中)。事实上,这里不能使用node.node_集来获取节点的foreignkey。为了使一个节点有多个子节点,必须使用ManyToManyField,例如:

children = models.ManyToManyField('self', null=True)
然后使用以下命令调用它:

node.children.all() # for all children

编辑

简要分析:

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

将返回所有以B为父对象的A,或所有以B为父对象的A。在您的情况下,您实际上有:

a = A()
b = A()
b.parent_set.all() 
将返回所有以b(=A)为父节点的A,在这种情况下,A.parent\u id=b.id,但b.id为None(未保存),因此将获得所有具有parent\u id=None的节点(b)


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

我已经测试了上面显示的代码,child_cnt()显示0,node_set.all()返回[]。对我来说,在指定的模型或应用程序中,似乎还有其他一些代码对模型进行了一些更改,使其行为类似于此。感谢您的提示,我忘记了在上面截取的代码中添加root.save()。我现在改正了。在我的机器上,即使对于一个新的Django项目,现在执行的行为也和我说的一样。我不知道。第二:没有节点集。all()不会作为objects.all()执行。尝试添加parent=root的第三个节点并保存它。在请求节点集时,您仍然只能获得根节点。第三:外键是一种多对一的关系。无论如何:我会看一看ManyToManyFields,但感觉很奇怪,因为每个节点必须只有一个父节点。那么为什么不使用多对一关系呢?是的,不完全像objects.all(),但更像objects.filter(pk=None)。大体上同意多对一,但这里使用起来很奇怪。。。正在计算当前节点的父节点的节点。。。这并非不可能,但似乎会引起问题。我的建议是在节点中有子节点,而不是父节点。毕竟,你在这里寻找的是孩子数。同意objects.filter(pk=None)。也许我应该在那里为Django提交一个bug。顺便说一句:我需要更多的功能不仅仅是儿童计数,但这是唯一给我带来麻烦的事情。所以我把剩下的都脱光了对于非递归关系也是如此——我已经更新了答案。通知Django开发人员是有道理的。我看过这个库,它似乎解决了我遇到的一些其他问题,所以我还是要导入它。谢谢你的提示!
a = A()
b = B()
b.parent_set.all() 
a = A()
b = A()
b.parent_set.all()