使用 Django 模版內建過濾器 unordered_list 實現樹形結構

weixin_34208283發表於2017-03-24

官方文件解釋:
Recursively takes a self-nested list and returns an HTML unordered list – WITHOUT opening and closing <ul> tags.

The list is assumed to be in the proper format. For example, if var contains ['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']], then {{ var|unordered_list }} would return:

<li>States
    <ul>
        <li>Kansas
            <ul>
                <li>Lawrence</li>
                <li>Topeka</li>
            </ul>
        </li>
        <li>Illinois</li>
    </ul>
</li>

接下來我們就來實現上面的效果。

環境版本:

  • python 2.7.10
  • Django 1.8.5

首先在 models.py 新增程式碼:

#coding:utf-8
from django.db import models


class Area(models.Model):
    name = models.CharField('名稱', max_length=50, unique=True)
    parent = models.ForeignKey('self', verbose_name='上級區域', null=True, blank=True, related_name='children')

    class Meta:
        db_table = 'area'
        verbose_name = verbose_name_plural = '省/市/地區(縣)'

    def __unicode__(self):
        return self.name

admin.py 新增程式碼:

from django.contrib import admin
from .models import Area


class AreaAdmin(admin.ModelAdmin):
    list_display = ('id', 'name', 'parent')

admin.site.register(Area, AreaAdmin)

然後在後臺新增資料。


2733312-95d79da3e491c646.png

按照官方文件的說法,顯示時傳遞給模版的資料應該是下面這種格式:

['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]

所以我們需要寫一個遞迴的工具函式。得到根節點,傳遞給 display,然後把 display 函式生成的列表傳遞給模版:

from django.shortcuts import render_to_response
from .models import Area

def display(areas):
    display_list= []
    for area in areas:
        display_list.append(area.name)

        children = area.children.all()
        if len(children) > 0:
            display_list.append(display(children))
    return display_list

def tree(request):
    areas = Area.objects.filter(parent=None)
    return render_to_response('tree.html', {'var': display(areas)})

最後在模板中新增:

{{ var|unordered_list }} 

就可以看到顯示效果了。


2733312-d7e6ec8aaa67953b.png

因為有時候需求不止這麼簡單,比如有時需要展現樣式等等,unordered_list 就遠遠不夠了。這個時候就需要使用 mptt,請參照我的另一篇文章 使用 django-mptt 實現樹形結構

相關文章