Brian Luft <brian@lincolnloop.com>
DjangoCon 2010 Portland, OR
Working with Django for a few years.
With Lincoln Loop since 2008.
Clients include National Geographic, PBS, Nasuni, and redbeacon.
Where do we find structured data?
A table is not a tree. We need a few tricks.
http://dev.mysql.com/tech-resources/articles/hierarchical-data.html
+-------------+----------------------+--------+ | category_id | name | parent | +-------------+----------------------+--------+ | 1 | ELECTRONICS | NULL | | 2 | TELEVISIONS | 1 | | 3 | TUBE | 2 | | 4 | LCD | 2 | | 5 | PLASMA | 2 | | 6 | PORTABLE ELECTRONICS | 1 | | 7 | MP3 PLAYERS | 6 | | 8 | FLASH | 7 | | 9 | CD PLAYERS | 6 | | 10 | 2 WAY RADIOS | 6 | +-------------+----------------------+--------+
Select whole tree:
1 SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4
2 FROM category AS t1
3 LEFT JOIN category AS t2 ON t2.parent = t1.category_id
4 LEFT JOIN category AS t3 ON t3.parent = t2.category_id
5 LEFT JOIN category AS t4 ON t4.parent = t3.category_id
6 WHERE t1.name = 'ELECTRONICS';
+-------------+----------------------+--------------+-------+ | lev1 | lev2 | lev3 | lev4 | +-------------+----------------------+--------------+-------+ | ELECTRONICS | TELEVISIONS | TUBE | NULL | | ELECTRONICS | TELEVISIONS | LCD | NULL | | ELECTRONICS | TELEVISIONS | PLASMA | NULL | | ELECTRONICS | PORTABLE ELECTRONICS | MP3 PLAYERS | FLASH | | ELECTRONICS | PORTABLE ELECTRONICS | CD PLAYERS | NULL | | ELECTRONICS | PORTABLE ELECTRONICS | 2 WAY RADIOS | NULL | +-------------+----------------------+--------------+-------+
Select one path:
1 SELECT t1.name AS lev1, t2.name as lev2, t3.name as lev3, t4.name as lev4
2 FROM category AS t1
3 LEFT JOIN category AS t2 ON t2.parent = t1.category_id
4 LEFT JOIN category AS t3 ON t3.parent = t2.category_id
5 LEFT JOIN category AS t4 ON t4.parent = t3.category_id
6 WHERE t1.name = 'ELECTRONICS' AND t4.name = 'FLASH';
+-------------+----------------------+-------------+-------+ | lev1 | lev2 | lev3 | lev4 | +-------------+----------------------+-------------+-------+ | ELECTRONICS | PORTABLE ELECTRONICS | MP3 PLAYERS | FLASH | +-------------+----------------------+-------------+-------+
http://dev.mysql.com/tech-resources/articles/hierarchical-data.html
Preorder tree traversal algorithm
+-------------+----------------------+-----+-----+ | category_id | name | lft | rgt | +-------------+----------------------+-----+-----+ | 1 | ELECTRONICS | 1 | 20 | | 2 | TELEVISIONS | 2 | 9 | | 3 | TUBE | 3 | 4 | | 4 | LCD | 5 | 6 | | 5 | PLASMA | 7 | 8 | | 6 | PORTABLE ELECTRONICS | 10 | 19 | | 7 | MP3 PLAYERS | 11 | 14 | | 8 | FLASH | 12 | 13 | | 9 | CD PLAYERS | 15 | 16 | | 10 | 2 WAY RADIOS | 17 | 18 | +-------------+----------------------+-----+-----+
http://dev.mysql.com/tech-resources/articles/hierarchical-data.html
Retrieve the whole tree
1 SELECT node.name
2 FROM nested_category AS node,
3 nested_category AS parent
4 WHERE node.lft BETWEEN parent.lft AND parent.rgt
5 AND parent.name = 'ELECTRONICS'
6 ORDER BY node.lft;
Query works regardless of the depth of tree.
+-------------+----------------------+--------+ | category_id | name | path | +-------------+----------------------+--------+ | 1 | ELECTRONICS | 1 | | 2 | TELEVISIONS | 1.1 | | 3 | TUBE | 1.1.1| | 4 | LCD | 1.1.2| | 5 | PLASMA | 1.1.3| | 6 | PORTABLE ELECTRONICS | 1.2 | | 7 | MP3 PLAYERS | 1.2.1| | 8 | FLASH | 1.2.2| | 9 | CD PLAYERS | 1.3 | | 10 | 2 WAY RADIOS | 1.4 | +-------------+----------------------+--------+
http://www.qompr.com/charts/63;django-hierarchical-tree-data/
Relational Model
Treebeard:
MPTT:
Forms / Admin
Both provide Move Node forms.
django-mptt provides a TreeNodeChoiceField (ModelChoiceField)
Active
django-mptt is being maintained
django-treebeard has slightly more active development
Front-end
Treebeard: get_annotated_list
MPTT: a few nice template tags / filters
Real-world Examples
django-treebeard: django-page-cms
django-mptt: django-cms
Overall Impressions
https://tabo.pe/projects/django-treebeard/docs/tip/benchmarks.html
Fast-forward:
1 mkvirtualenv treehugging
2 pip install -e git+http://github.com/batiste/django-mptt.git#egg=django-mptt
3 pip install django-treebeard
4 pip install django-extensions
5 pip install ipython
6 django-admin.py startproject treehugging
7 django-admin.py startapp demo_mptt
Managing Hierarchical Data in MySQL
http://dev.mysql.com/tech-resources/articles/hierarchical-data.html
Working With Taxonomy Trees using Django and jQuery
http://www.quanative.com/2010/01/01/working-with-taxonomy-trees-using-django-and-jquery/
django-treebeard docs
https://tabo.pe/projects/django-treebeard/docs/1.61/
Django Tree Libraries
http://blog.elsdoerfer.name/2010/02/28/django-tree-libraries/