2011-03-08 29 views
4

我如何在django模板中使用django-mptt实现树结构。django模板中父子关系的树结构

我有模型。

class Person(TimeStampedModel): 
    name = models.CharField(max_length=32) 
    parent  = models.ForeignKey('self', null=True, blank=True, related_name='children') 

现在我想..

Parent 
    Child 1 
     subchild 1.1 
     subchild 1.2 
      nextsubchild 1.2.1 
    Child 2 
    Child 3 

有名称应点击能够展现自己的个人资料。

回答

9
Django while loop问题

http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#inclusion-tags

# view.py 

@register.inclusion_tag('children.html') 
def children_tag(person): 
    children = person.children.all() 
    return {'children': children} 

# children.html 

<ul> 
    {% for child in children %} 
    <li> <a href="{{ child.get_absolute_url }}">{{ child }}</a></li> 
     {% if child.children.count > 0 %} 
     {% children_list child %} 
     {% endif %} 
    {% endfor %} 
</ul> 


# your template 

{% children_tag parent %} 
+0

发生错误“调用Python对象时超出最大递归深度”,现在可以帮助我吗? – Ahsan 2011-03-08 10:34:07

+0

@Ahsan lemme看看 – DTing 2011-03-08 10:51:36

+0

我认为包括for循环创建问题,否则代码是如此的好。 – Ahsan 2011-03-08 11:08:03

11

我只是完成实现此。我想要一个子导航树形结构,但我不想对递归模板做任何奇怪的事情。

我实现的解决方案非常简单:我只是在视图中递归(在我的情况下是泛型辅助函数),并将层次结构展平成一个简单的列表。然后,在我的模板中,我只是使用for循环遍历列表。

列表中的每个元素都可以是以下三种情况之一:“in”,对象或“out”。就我而言,我在视图中构建了一系列ul li元素,所以当遇到“in”时,我创建了一个新的ul,当我遇到“out”时,我关闭了ul。否则,我呈现该项目。

我的模板代码看起来是这样的:

      {% for item in sub_nav %}  
           {% if item == "in" %}   
            <ul> 
           {% else %}      
            {% if item == "out" %}    
              </ul>     
             </li>     
            {% else %}      

              <li>       
               <a href='{{item.full_url}}'>{{item.name}}</a> 
               {% if item.leaf %}   
               </li>      
               {% endif %}   

            {% endif %}   
           {% endif %}   
          {% endfor %} 

在辅助函数的代码如下所示:

def get_category_nav(request,categories=None): 
"""Recursively build a list of product categories. The resulting list is meant to be iterated over in a view""" 
if categories==None: 
    #get the root categories 
    categories = ProductCategory.objects.filter(parent=None) 
    categories[0].active=True 
else: 
    yield 'in' 

for category in categories: 
    yield category 
    subcats = ProductCategory.objects.select_related().filter(parent=category) 
    if len(subcats): 
     category.leaf=False 
     for x in get_category_nav(request,subcats): 
      yield x 
    else: 
     category.leaf=True 
yield 'out' 

使用这些片段,你应该能够建立任何形式的分层树你希望没有在模板中做任何递归,并保持视图中的所有逻辑。

我知道已经有一个可以接受的答案,但我想我会发布技术以防其他人帮助。

+0

感谢Clayton Gulick ..很好的答案.. – Ahsan 2011-04-15 06:10:26

+0

不明白为什么这没有得到更多的积分,直到现在的最佳答案!老兄,出色的工作,使用模板标签要好得多,这是我到目前为止跨越的唯一MVC解决方案,并且工作得非常棒,速度非常快,非常棒! – Erez 2011-05-23 11:40:58

+0

我真的很喜欢这个。不幸的是,我的树结构显示在表格中,所以我需要''div style =“margin-left:%d * level”> ...'。所以我放弃了''in''和''out''条目,并用css东西添加了属性助手来将其自身添加到对象中。 – SummerBreeze 2014-01-07 13:28:07

2

这些都是很好的答案,但我巩固了一下,并把它放在实际的模型上。

class RecursiveThing(models.Model): 

    name = models.CharField(max_length=32) 
    parent = models.ForeignKey('self', related_name='children', blank=True, null=True) 

    def as_tree(self): 
     children = list(self.children.all()) 
     branch = bool(children) 
     yield branch, self 
     for child in children: 
      for next in child.as_tree(): 
       yield next 
     yield branch, None 

,然后在模板:

<ul> 
    {% for thing in things %} 
     {% for branch, obj in thing.as_tree %} 
      {% if obj %} 
       <li>{{ obj.name }} 
       {% if branch %} 
        <ul> 
       {% else %} 
        </li> 
       {% endif %} 
      {% else %} 
       {% if branch %} 
        </ul> 
       {% endif %} 
      {% endif %} 
     {% endfor %} 
    {% endfor %} 
</ul> 
+1

你的答案是有效的,但是在模板中它显示了父母和他们的孩子,但是低一点,它显示了同样的孩子,但是作为父母(((如何修复它? – 2013-05-18 17:04:43

+1

)你想解释一下你的代码@sheats? – 2016-12-30 07:00:09

0

这很简单

所有你有你的观点做的就是让所有对象:

people = Person.objects.all() 

然后在你的模板:

{% for person in people %} 
    <li>- {{person.name}} </li> 
    {% for child in person.children.all %} 
    <ul>* {{child.nom}} </ul> 
    {% endfor %} 
</li>   
{% endfor %}