This is a follow up to the previous post on managing and visualizing trees using django. I've been using MPTT quite a bit now and it's great - also, I looked deeper into the admin integration (basically, the issue of being able of manage trees from within the admin).
The solution has been to reuse the admin management section from the FeinCMS project - this is a great CMS created by a bunch of django-ers in Switzerland - it relies heavvily on django's admin so they had the same problem when having to provide a way for users to add structure to the pages in a website. With some help from google and Matthias (tx! he's one of the guys behind FeinCMS) I got it all working.. here's the main steps:
1. upgrade to django 1.1 This might not be necessary, cause everything is supposed to work also with the previous release - I tried it with django 1.0 too but I had to fix a couple of urls to make it work (Basically media files which were not loaded properly). So, if you want a hassle-free installation just upgrade to django 1.1 ! (which is great btw)
INSTALLED_APPS = ( .... 'mptt', 'feincms', )
3. specify a url-path for feincms media in settings.py, and also a location (this may vary in your live server, if you want apache to serve these files directly).
FEINCMS_ADMIN_MEDIA = '/feincms_media/' FEINCMS_ADMIN_MEDIA_LOCATION = '/My/local/path/to/feincms/media/'
4. add a url handler for feincms media files in urls.py. Again, these settings are ok on a development server, on production phase you might wanna do things differently :-)
from django.conf import settings
urlpatterns = patterns('',
5. register your hierarchical model with mptt, then remember to set the Meta option correctly.. this is needed for a correct display of the tree in the admin (obviously you need to run syncdb to create the table in the db!):
from django.db import models import mptt
class TreeNode(models.Model): name = models.CharField(max_length=50, unique=True) parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
def __unicode__(self): return self.name
class Meta: ordering = ['tree_id', 'lft']
6. create a model admin that inherits from feincms TreeEditor class:
from django.contrib import admin from django.utils.translation import ugettext_lazy as _ from django.conf import settings as django_settings from feincms.admin import editor from myproject.myapp.models import *
class TreeNodeAdmin(editor.TreeEditor): pass
End! That should be it! Let me know if I forgot something.. Here's a screenshot of the new tree-management admin page we created:
UPDATE 09/2009: how to add more actions to the tree bar. Just override the _actions_column method on the TreeNodeAdmin class, as follows::
class TreeNodeAdmin(editor.TreeEditor): def _actions_column(self, page): actions \= super(TreeNodeAdmin, self)._actions_column(page) actions.insert(0, u'<a href\="add/?parent=%s" title\="%s"><img src\="%simg/admin/icon_addlink.gif" alt\="%s"></a>' % (page.pk, _('Add child page'), settings.ADMIN_MEDIA_PREFIX , _('Add child page'))) actions.insert(0, u'<a href\="%s" title\="%s"><img src\="%simg/admin/selector-search.gif" alt\="%s" /></a>' % (page.get_absolute_url(), _('View on site'), django_settings.ADMIN_MEDIA_PREFIX, _('View on site'))) return actions
Cite this blog post:
blog Django signals
blog UML to django
blog Offline django docs