2011-03-08 58 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 %}