### Navigation

- index
- modules |
- next |
- previous |
- django-mptt 0.6.0 documentation »

# Tutorial

## The Problem

You’ve created a Django project, and you need to manage some hierarchical data. For instance you’ve got a bunch of hierarchical pages in a CMS, and sometimes pages are children of other pages

Now suppose you want to show a breadcrumb on your site, like this:

    Home > Products > Food > Meat > Spam > Spammy McDelicious

To get all those page titles you might do something like this:

    titles = []
    while page:
        titles.append(page.title)
        page = page.parent

That’s one database query for each page in the breadcrumb, and database queries are slow. Let’s do this a better way.

## The Solution

Modified Preorder Tree Traversal can be a bit daunting at first, but it’s one of the best ways to solve this problem.

If you want to go into the details, there’s a good explanation here: Storing Hierarchical Data in a Database or Managing Hierarchical Data in Mysql

tl;dr: MPTT makes most tree operations much cheaper in terms of queries. In fact all these operations take at most one query, and sometimes zero:
  - get descendants of a node
  - get ancestors of a node
  - get all nodes at a given level
  - get leaf nodes
And this one takes zero queries:
  - count the descendants of a given node

Enough intro. Let’s get started.

## Getting started

### Add `mptt` To `INSTALLED_APPS`

As with most Django applications, you should add `mptt` to the `INSTALLED_APPS` in your `settings.py` file:

    INSTALLED_APPS = (
        'django.contrib.auth',
        # ...
        'mptt',
    )

### Set up your model

Start with a basic subclass of MPTTModel, something like this:

    from django.db import models
    from mptt.models import MPTTModel, TreeForeignKey

    class Genre(MPTTModel):
        name = models.CharField(max_length=50, unique=True)
        parent = TreeForeignKey('self', null=True, blank=True, related_name='children')

        class MPTTMeta:
            order_insertion_by = ['name']

You must define a parent field which is a `TreeForeignKey` to `'self'`. A `TreeForeignKey` is just a regular `ForeignKey` that renders form fields differently in the admin and a few other places.

Because you’re inheriting from MPTTModel, your model will also have a number of other fields: `level`, `lft`, `rght`, and `tree_id`. These fields are managed by the MPTT algorithm. Most of the time you won’t need to use these fields directly.

That `MPTTMeta` class adds some tweaks to `django-mptt` - in this case, just `order_insertion_by`. This indicates the natural ordering of the data in the tree.

Now create your table in the database:

    python manage.py syncdb

### Create some data

Fire up a django shell:

    python manage.py shell

Now create some data to test:

    from myapp.models import Genre
    rock = Genre.objects.create(name="Rock")
    blues = Genre.objects.create(name="Blues")
    Genre.objects.create(name="Hard Rock", parent=rock)
    Genre.objects.create(name="Pop Rock", parent=rock)

### Make a view

This one’s pretty simple for now. Add this lightweight view to your `views.py`:

    def show_genres(request):
        return render_to_response("genres.html",
                              {'nodes':Genre.objects.all()},
                              context_instance=RequestContext(request))

And add a URL for it in `urls.py`:

    (r'^genres/$', 'myapp.views.show_genres'),

### Template

`django-mptt` includes some template tags for making this bit easy too. Create a template called `genres.html` in your template directory and put this in it:

    {% load mptt_tags %}
    <ul>
        {% recursetree nodes %}
            <li>
                {{ node.name }}
                {% if not node.is_leaf_node %}
                    <ul class="children">
                        {{ children }}
                    </ul>
                {% endif %}
            </li>
        {% endrecursetree %}
    </ul>

That recursetree tag will recursively render that template fragment for all the nodes. Try it out by going to `/genres/`.

There’s more; check out the docs for custom admin-site stuff, more template tags, tree rebuild functions etc.

Now you can stop thinking about how to do trees, and start making a great django app!

### Navigation

- index
- modules |
- next |
- previous |
- django-mptt 0.6.0 documentation »