Django内置unordered_list和django-mptt模块实现树形结构

一、Django 模版内置过滤器 unordered_list 实现树形结构

官方文档解释:
Recursively takes a self-nested list and returns an HTML unordered list – WITHOUT opening and closing

    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:

  • States
    • Kansas
      • Lawrence
      • Topeka
    • Illinois
  • 接下来我们就来实现上面的效果。

    环境版本:

    • 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)
    

    然后在后台添加数据。

    Django内置unordered_list和django-mptt模块实现树形结构_第1张图片

    按照官方文档的说法,显示时传递给模版的数据应该是下面这种格式:

    ['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 }} 
    

    就可以看到显示效果了。

    Django内置unordered_list和django-mptt模块实现树形结构_第2张图片

    因为有时候需求不止这么简单,比如有时需要展现样式等等,unordered_list 就远远不够了。这个时候就需要使用 mptt。

    二、django-mptt模块实现树形结构

    在 Web 开发中,省/市/区(县)是经常需要用到的数据,而省/市/区(县)是一种层级关系。在使用 Django 做 Web 开发时,此时 Django-mptt 是一个很有用的模块。

    环境版本:

    • python 2.7.10
    • Django 1.8.5
    • django-mptt 0.8.7

    安装 django-mptt

    pip install django-mptt
    

    新建 area 应用

    startapp area
    

    models.py 里添加如下代码:

    #coding:utf-8
    from django.db import models
    from mptt.models import MPTTModel
    
    
    class Area(MPTTModel):
        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
    

    在这里只需让 Area 继承 MPTTModel
    需要说明的是,实际上 MPTTModel 隐藏了四个变量:levellftrghttree_id。大多数时候我们是用不到这几个变量的。另外,如果你的 Modelparent 变量名字不是 "parent" 时,应当在 ModelMPTT 元类中指明:

    #coding:utf-8
    from django.db import models
    from mptt.models import MPTTModel
    
    
    class Area(MPTTModel):
        name = models.CharField('名称', max_length=50, unique=True)
        parent_area = models.ForeignKey('self', verbose_name='上级区域', null=True, blank=True, related_name='children')
    
        class Meta:
            db_table = 'area'
            verbose_name = verbose_name_plural = '省/市/地区(县)'
    
        class MPTTMeta:
            parent_attr = 'parent_area'
    
        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', 'level')
    
    admin.site.register(Area, AreaAdmin)
    

    在项目的 settings.pyINSTALLED_APPS 里添加 mpttarea,之后执行数据库操作。之后在 admin 后台中按照层级关系添加省/市/区(县)数据。

    Django内置unordered_list和django-mptt模块实现树形结构_第3张图片

    views.py 里添加如下代码:

    from django.shortcuts import render_to_response
    from .models import Area
    
    
    def tree(request):
        nodes = Area.objects.all()
        return render_to_response('tree.html', {'nodes': nodes})
    

    templates 文件夹下添加模版文件 tree.html

    {% load staticfiles %}
    {% load mptt_tags %}
    
    
    
        
        Django 树形结构
        
        
        
        
    
    
        

    别忘了在 settings.py 里添加如下代码:

    STATIC_ROOT = os.path.join(BASE_DIR, 'static')
    STATICFILES_DIRS = [
        ('css', os.path.join(STATIC_ROOT, 'css')),
        ('js', os.path.join(STATIC_ROOT, 'js')),
        ('img', os.path.join(STATIC_ROOT, 'img')),
    ]
    

    否则获取不到静态资源!
    最后在项目的 urls.py 里添加如下代码:

    from area.views import tree
    
    urlpatterns = [
        ...
        url(r'^tree/', tree),
        ...
    ]
    

    这样,就可以通过访问 http://127.0.0.1:8000/tree/ 看到树形结构了。

    Django内置unordered_list和django-mptt模块实现树形结构_第4张图片

    具体代码可以参看我在 github 上的 tree 仓库。

你可能感兴趣的:(#,Django)