Tree-structured menuing application for Django.
Project description
This is a simple and generic tree-like menuing system for Django with an easy-to-use admin interface. It covers all the essentials for building tree-structured menus and should be enough for a lot of projects. It is also easily extendable if you need to add some special behaviour to your menu items.
django-treemenus works with Django 1.0 and above and with python 2.5 and above.
Installation
Installing an official release
django-treemenus is available on PyPI, and can be installed using Pip:
pip install django-treemenus
Alternatively, official source releases are made available at https://pypi-hypernode.com/pypi/django-treemenus
Download the .zip distribution file and unpack it. Inside is a script named setup.py. Run this command:
python setup.py install
…and the package will install automatically.
Installing the development version
If you prefer to update Django Tree Menus occasionally to get the latest bug fixes and improvements before they are included in an official release, do a git clone instead:
git clone https://github.com/jphalip/django-treemenus
Then add the treemenus folder to your PYTHONPATH or symlink (junction, if you’re on Windows), such as in your Python’s site-packages directory.
Basic use
To build a menu, log into the admin interface, and click “Menus” under the Treemenus application section, then click “Add menu”. Give your new menu a name and then save.
Then, to create menu items, click on your menu in the menu list. You will then see a table in the bottom part of the page with only one item: the menu’s root. Click “Add an item”, select its parent (obviously, since this is the first item you’re creating you can only select the root). Fill out the item’s details and click “Save”. The new item now shows up in the table. Now keep going to build the whole structure of your tree menu by creating as many branches as you like.
When you’ve finished building your menu from the admin interface, you will have to write the appropriate templates to display the menu on your site (see below).
Attributes and methods
As you’ve guessed it, you can manipulate two types of objects: menus and menu items. In this section I present their attributes and methods, which you can use in your templates.
Customizing/Extending
The attributes and methods enumerated above provide the essential behaviour for a tree-structured menu. If that is not enough for you, it is also possible to add customized behaviour by extending the menu item definition. To do so, you need to create a model class that will contain all the extra attributes for your menu items.
To illustrate this, let’s say that you’d like to add a published attribute to your menu items so that they only show up on your site if published is turned to True.
To do so, create a new application (let’s call it menu_extension), with the following structure:
menu_extension __init__.py models.py forms.py
Then, in menu_extension.models.py add the following:
from django.db import models from treemenus.models import MenuItem class MenuItemExtension(models.Model): menu_item = models.OneToOneField (MenuItem, related_name="extension") published = models.BooleanField(default=False)
It is required that your extension object has the attribute menu_item that is a unique link to a menu item object. This is what makes the extension possible. Then you can notice our attribute published, feel free to add any other attribute there to customize your menu items.
You then need to create the database table that will store your extension data by adding menu_extension to the INSTALLED_APPS setting of your Django project, and then running the following command from the root of your project:
python manage.py syncdb
Now, you need to specify a form to let you edit those extra attributes from the admin interface. In your project’s admin.py or your extension menu app’s admin.py, add the following:
from django.contrib import admin from treemenus.admin import MenuAdmin, MenuItemAdmin from treemenus.models import Menu from menu_extension.models import MenuItemExtension class MenuItemExtensionInline(admin.StackedInline): model = MenuItemExtension max_num = 1 class CustomMenuItemAdmin(MenuItemAdmin): inlines = [MenuItemExtensionInline,] class CustomMenuAdmin(MenuAdmin): menu_item_admin_class = CustomMenuItemAdmin admin.site.unregister(Menu) # Unregister the standard admin options admin.site.register(Menu, CustomMenuAdmin) # Register the new, customized, admin options
And that’s it! Now, when creating or editing a menu item, you’ll see an inline form with all the extension attributes (in this example, the published check box).
Now, if you want to use published attribute in your template, you need to use the menu item’s extension method, as follows:
{% if menu_item.extension.published %} <li><a href="{{ menu_item.url }}">{{ menu_item.caption }}</a></li> {% endif %}
Your menu items will now only appear if their published check box has been ticked.
Using this technique, you can obviously extend your menu items with whatever attribute you’d like. Other examples might be that you want to add special CSS styles to certain menu items, or to make some of them show up only if the user is logged in, etc. Simply add attributes in you extension model and make use of them in your templates to create special behaviour. See the ‘Tips and Tricks’ section for more ideas.
Tips and tricks
In this section I give some examples on using or extending menus. These may just cover some of your own specific needs or at least inspire you and get you started to make the most out of your menus.
Internationalization
Making your menus multi-lingual is very easy if you use the Django internationalization module. What you can do is apply the translation to the caption attribute of a menu_item. For example:
{% load i18n %} ... <li><a href="{{ menu_item.url }}">{% trans menu_item.caption %}</a></li>
Then, add manually the translation entries in your *.po file.
If you use more complex or custom translation systems, you may simply define your extension class (or create it if you don’t already have one) with a method to manage the translation, for example:
class MenuItemExtension(models.Model): menu_item = models.OneToOneField (MenuItem, related_name="extension") ... def translation(): translation = do_something_with(self.menu_item.caption) return translation
And then in your template:
<li><a href="{{ menu_item.url }}">{% trans menu_item.extension.translation %}</a></li>
Login restriction
If you want to make some of your menus items private and only available to logged in users, that’s simple! Simply define your extension class (or create it if you don’t already have one) like the following:
class MenuItemExtension(models.Model): menu_item = models.OneToOneField (MenuItem, related_name="extension") protected = models.BooleanField(default=False) ...
And then in your template:
{% if menu_item.extension.protected %} {% if user.is_authenticated %} <li><a href="{{ menu_item.url }}">{{ menu_item.caption }}</a></li> {% endif %} {% else %} <li><a href="{{ menu_item.url }}">{{ menu_item.caption }}</a></li> {% endif %}
(assuming that the context variable ‘user’ represents the currently logged-in user)
That’s it!!
Please log any issue or bug report at https://github.com/jphalip/django-treemenus/issues
Enjoy!
Julien Phalip (project developer)
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.