确定django-mptt中每个级别的“last”元素

时间:2012-01-05 20:01:29

标签: django django-mptt

我正在尝试生成类似于以下内容的列表:

<ul>
    <li>Parent 1
        <ul>
            <li>Child 1</li>
            <li>Child 2</li>
            <li class="last">Child 3</li>
        </ul>
    </li>
    <li>Parent 2
        <ul>
            <li>Child 1</li>
            <li>Child 2</li>
            <li class="last">Child 3</li>
        </ul>
    </li>
    <li class="last">Parent 3
        <ul>
            <li>Child 1</li>
            <li>Child 2</li>
            <li class="last">Child 3</li>
        </ul>
    </li>
</ul>

我原本刚刚做过:

<ul>
    {% recursetree mytree %}
    <li class="{% if not node.get_next_sibling %}last{% endif %}">
        {{ node }}
        {% if not node.is_leaf_node %}
        <ul>
            {{ children }}
        </ul>
        {% endif %}
    </li>
</ul>

但是,对node.get_next_sibling的调用会导致对每个项目进行额外查询。显然,这并不理想。所以我尝试使用tree_infostructure.closed_levels来确定最后一项:

{% for node,structure in mytree|tree_info %}
    {% if structure.new_level %}<ul><li>{% else %}</li><li>{% endif %}
        <li class="{% if structure.closed_levels|length > 0 %}last{% endif %}">
            {{ node }}
    {% for level in structure.closed_levels %}</li></ul>{% endfor %}
{% endfor %}

这很好用,除了最后一个根级别项没有获得“last”类,因为它的structure.closed_levels始终是一个空列表。 (它真的只适用于儿童用品)。

我确信我不是第一个需要完成类似工作的人,所以我希望这里有人可能已经有了解决方案。

2 个答案:

答案 0 :(得分:1)

我想您应该能够从MPTT订单信息中获取所需信息。这是一个good intro to how MPTT works(从django-mptt docs链接)。关键是保持对父母的引用,这样你就可以检查你的节点的“正确”属性是否比你父母的“左”少一个。

django-mptt特殊情况下的根节点,让你拥有多棵树。如果你在一棵树上迭代节点,那么这样的东西应该有效(虽然我还没有测试过):

<ul class="root">
    {% recursetree nodes %}
        <li class="{% if parent == None or node.rgt|plusone == parent.lft %}last{% endif %}">
            {{ node.name }}
            {% if not node.is_leaf_node %}
                {% with node as parent %}
                <ul class="children">
                    {{ children }}
                </ul>
                {% endwith %}
            {% endif %}
        </li>
    {% endrecursetree %}
</ul>

但是,如果“nodes”包含所有根的列表,则需要明确捕获它。这样的事情可以解决问题:

{% with nodes|last as lastnode %}
<ul class="root">
    {% recursetree nodes %}
        <li class="{% if node == lastnode or parent and node.rgt|plusone == parent.lft %}last{% endif %}">
            {{ node.name }}
            {% if not node.is_leaf_node %}
                {% with node as parent %}
                <ul class="children">
                    {{ children }}
                </ul>
                {% endwith %}
            {% endif %}
        </li>
    {% endrecursetree %}
</ul>
{% endwith %}

您会注意到上面的代码引用了“plusone”模板过滤器。这样的事情应该做:

from django import template

register = template.Library()

@register.filter
def plusone(value):
    return value + 1

所有这一切,根据我的喜好,这是一个太多的模板计算。如果这是你经常做的事情,将它包装在自定义模板标签中可能是明智的。

答案 1 :(得分:0)

你应该使用{{forloop.last}}{{if 1 == forloop.revcounter}} 最后一个是{{if 2 == forloop.revcounter}}

使用django逻辑添加类...

如果您只是想添加样式,可以使用css选择器:last-child而不是添加类

如果你需要javascript并使用jquery

选择器来为jquery工作