在Django模型中创建树结构?

14 投票
3 回答
21818 浏览
提问于 2025-04-17 19:33

我想在Django中创建一个模型,这个模型有两个字段,分别是孩子和父母。我该怎么做呢?我现在有这样的代码:

from django.db import models
class FooModel(models.Model)
    parent = models.ForeignKey('self', blank=True, null=True)
    children = models.ManyToOneRel('self', blank=True, null=True)

    def __init__(self, *args, **kwargs):
        super(FooModel, self).__init__(*args, **kwargs)
        self.parent.children.add(self)

但是我觉得我不应该这样使用ManyToOneRel(尤其是因为它在'blank'上给我报了个关键字错误)。你有什么建议吗?

3 个回答

0

我找不到关于 ManyToOneRel 的文档,所以我去查了它的 代码

def __init__(self, to, field_name, related_name=None, limit_choices_to=None,
        parent_link=False, on_delete=None):

从代码中可以看到,没有 blank 这个参数。

3
class FooModel(models.Model)
    parent = models.ForeignKey('self', blank=True, null=True, related_name='children')


FooModel.objects.get(pk=1).children.all()

如果你想要使用缓存,可以随便选择你喜欢的方式:比如把查询结果缓存起来,或者把所有子项作为一个简单的列表存储在父项中,记得要处理新添加的实体,以便更新这个列表。ManyToOneRel是Django内部需要用到的东西,而且它不是Field类的一个实例。

30

ManyToOneRel 是一个内部实现的类,不是用来在你的模型中使用的。

但是你为什么觉得自己需要它呢?正如文档详细解释的,当你定义一个外键(ForeignKey)时,你会自动获得一个反向关系。所以在你的情况下,如果你定义了 parent,那么你就会自动得到 self.foomodel_set:你还可以通过使用 related_name 参数来让这个关系更加明确:

parent = models.ForeignKey('self', blank=True, null=True, related_name='children')

需要注意的是,如果你打算处理复杂的树形结构,可能更适合使用 django-mptt 这个库。

撰写回答