Django和MPTT - 获取仅叶节点

16
我刚接触Django和MPTT,很难弄清楚如何获取所有叶节点并将它们直接发送到Form类。例如,我创建了MPTT Category Model,并具有以下层次结构:
  • Category1
    • Category2
    • Category3
  • Category4
    • Category5
    • Category6
因此,我只想获取叶类别(cat2,3,5,6)。我的Form类看起来像这样:
class UploadForm(forms.Form):
    description = forms.CharField(max_length=50)
    category = mpttform.TreeNodeMultipleChoiceField(queryset=Category.objects.all())
    file = forms.FileField() 

使用queryset=Category.objects.all(),我得到的结果与上面完全一样-所有类别和它们的子类别。有没有办法只获取叶节点(子节点),但是从所有类别中获取叶节点,而不是特定类别实例中的叶节点?谢谢。

5个回答

21

我已经有一段时间没有使用Django MPTT了,但是考虑到叶子节点可以通过 right == left + 1 进行识别,您应该能够使用 F()表达式 进行筛选。


8
谢谢!解决方案是 Category.objects.filter(lft=F('rght')-1)。 - Zed
我曾以为这对于Django 1.4.5和Django MPTT 0.5.5适用,但后来发现它仍然返回根节点。看起来Category.objects.filter(level__gt=0)是更好的方法,不是吗? - Nate Beaty

15
Category.objects.filter(children__isnull=True)

我不知道这个解决方案是否会有任何性能问题,但这很简单明了!在这种情况下,“children”是MPTT模型上您所称呼的父关系的“related_name”。 - RSmithlal

2

不太优化的解决方案:

Category.objects.filter(id__in=[category.id for category in Category.objects.all() if category.is_leaf_node()])

0

我的 Django mptt 小片段

从 django.db 中导入 models

class CategoryManager(models.Manager):
    def get_leaf(self, level=2):
        return self.filter(level__lte=level).order_by('tree_id','lft').all()

class Category(models.Model):
     objects = CategoryManager()

利润,使用它:Catalog.objects.get_leaf()


0

来自文档:

is_leaf_node()

返回翻译的文本:

如果这个模型实例是一个叶节点(它没有子节点),则返回True,否则返回False


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接