版权所有,转载请注明出处:http://guangboo.org/2013/03/13/display-tree-with-django-template
django的template为我们提供了大量的tag,filter等,并且我们可以自己定义tag和filter以满足各自的需求。前一篇文章我们提供了如何在admin界面中显示树状结构,现在我们要在web前提也要显示,但是现实的效果不再是select的形式,而是使用ul,li标签来暂时树的层次,并且这种方式跟前篇文章的方式比起来,才是真正的嵌套。以为前者只是使用缩进来体现出层次感,本文将真实的使用嵌套的方式来实现层次性。
这里再次定义一下Category类:
class Category(models.Model): name = models.CharField('Category Name', max_length = 100, blank = False) slug = models.SlugField('URL', db_index = True) parent = models.ForeignKey('self', related_name='categories', null = True, blank = True)
那么当我们要从数据库中获取树的根节点时,可以这样写:
roots = Category.objects.filter(parent = None)
获取节点node的所有子节点就可以这样:
children = node.categories.all()
以上代码是我们在web前台实现树的必要的代码,也是准备工作。这里我们通过定义自己的tag来实现树的展示。django提供了一个简单方法来实现tag的自定义,template.inclusion_tag方法,也可以叫修饰器。定义tag的代码如下,tag的定义应该定义在app/templatetags目录下,这里py文件命名为category_tags.py:
from django import template from app.models import Category template = template.Library() @template.inclusion_tag("app/includes/category_tree_part.html") def category_tree(cate): return {'categories':cate.categories.all()}
代码中category_tree_part.html为树节点的模板,该模板也非常的简单,如下:
{% load category_tags %} {% if categories %}</pre> <ul>{% for cate in categories %} <li>{{ cate.name }} {% category_tree cate %}</li> {% endfor %}</ul> <pre class="brush:xml;">{% endif %}
代码中load category_tags,就是前面定义tag的py文件名。这里只是tag的模板,该模板需要在web的页面中使用,使用的方式也与模板中的定义差不多,文件名为category.html。如下:
{% extends "base.html" %} {% block content %} {% load category_tags %} {% category_tree categories %} {% endblock %}
是不是 很简单啊,只有加载category_tags库,然后调用tag:“category_tree categories”,这里的categories当然是所有跟目录里。这就需要views里面要将所有跟目录的节点提取出来。如定义view名称为category_view,那么定义为:
from django.http import HttpResponse from django.shortcuts import get_object_or_404, render_to_response from app.models import Category def category_view(request): return render_to_response('app/category.html', {'categories':Category.objects.filter(parent = None)})
这样就可以在web前台展示tree了。