【问题标题】:Writing an efficient node.all_siblings_leaf() method for django-mptt为 django-mptt 编写一个高效的 node.all_siblings_leaf() 方法
【发布时间】:2020-08-22 04:04:10
【问题描述】:

我有一个标签系统,其中标签存在于层次结构中。我使用django-mptt 来构建标签模型。如果组中的每个兄弟节点都是叶节点,我想以不同的方式显示一组标签。

为此,我需要一个名为all_siblings_leaf() 的模型方法。这是我对这种方法的第一次看法:

    def all_siblings_leaf(self):
        """Return True if all siblings, including self, are leaf nodes."""
        siblings = self.get_siblings()
        return all([sibling.is_leaf_node() for sibling in siblings])

这行得通,但这是get_siblings() 调用的一次数据库之旅。当我想调用all_siblings_leaf() 时,我已经查询了我想要使用的所有标签。对一组数百个标签重复使用此方法意味着数百个新的数据库调用。

由于我已经拥有所有标签,我觉得我应该能够获得有关叶节点的信息,而无需额外访问 db。这是我想出的:

    def all_siblings_leaf(self, all_tags):
        """Return True if all siblings including self are leaf nodes.

        all_tags should be a queryset that used select_related('parent')
        """
        if self.level == 0:
            siblings = [t for t in all_tags if t.level == 0]
        else:
            siblings = [t for t in all_tags if t.parent == self.parent]

        return all([sibling.is_leaf_node() for sibling in siblings])

这行得通;在多次使用此方法的页面上,通过调试工具栏测量到的数据库只有一次。

这感觉真的很麻烦,遍历其他节点并检查它是否具有相同的父节点,因为我们已经获取了每个标签的父节点信息。这是一种合理的方法,还是有更简单的解决方案?我在循环标签时从模板调用该方法,如果这有影响的话。

【问题讨论】:

  • 嗨!你已经想通了吗?
  • @AndreyNelubin,我没有比这更好的了。我对 MPTT 进行了更多研究,我发现我检查父母的方法与默认的 mptt 方法非常相似。但是经过进一步思考,我想知道是否有一种有效的方法可以跟踪右标签,直到标签具有不同的父标签,然后在树的左边做同样的工作。我仍然需要使用我自己的方法,传入 all_tags。
  • 这个问题很有趣,我会在这个周末考虑一下

标签: python django django-mptt


【解决方案1】:

好的。首先我们有这个answer

所以你的方法是:

def all_siblings_is_leaf(self, include_self=False):
    siblings = self.get_siblings(include_self=include_self)
    return siblings.annotate(
        descendants_count=Floor(
            (F(self._mpttfield('right')) - F(self._mpttfield('left')) - 1) / 2
        )
    ).values(
        'descendants_count'
    ).aggregate(
        total_count=Sum('descendants_count')
    )['total_count'] == 0

这会导致 1 个数据库请求。欲了解更多信息,请查看相关答案链接

【讨论】:

    猜你喜欢
    • 2011-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-31
    • 2022-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多