It is pretty easy to integrate your own Django applications with django-cms. You have 5 ways of integrating your app:
Menus
Static extend the menu entries
AttachMenus
Attach your menu to a page.
App-Hooks
Attach whole apps with optional menu to a page.
Navigation Modifiers
Modify the whole menu tree
Custom Plugins
Display your models / content in cms pages
With App-Hooks you can attach whole Django applications to pages. For example you have a news app and you want it attached to your news page.
To create an apphook create a cms_app.py in your application. And in there write the following:
from cms.app_base import CMSApp
from cms.apphook_pool import apphook_pool
from django.utils.translation import ugettext_lazy as _
class MyApphook(CMSApp):
name = _("My Apphook")
urls = ["myapp.urls"]
apphook_pool.register(MyApphook)
Replace “myapp.urls” with the path to your applications urls.py.
Now edit a page and open the advanced settings tab. Select your new apphook under “Application”. Save the page.
** ATTENTION ** If you are on a multi-threaded server (mostly all webservers, except the dev-server): Restart the server because the URLs are cached by Django and in a multi-threaded environment we don’t know which caches are cleared yet.
If you attached the app to a page with the url /hello/world/ and the app has a urls.py that looks like this:
from django.conf.urls.defaults import *
urlpatterns = patterns('sampleapp.views',
url(r'^$', 'main_view', name='app_main'),
url(r'^sublevel/$', 'sample_view', name='app_sublevel'),
)
The ‘main_view’ should now be available at /hello/world/ and the ‘sample_view’ has the url ‘/hello/world/sublevel/’.
Note
All views that are attached like this must return a RequestContext instance instead of the default Context instance.
Language Namespaces
An additional feature of apphooks is that if you use the MultilingualURLMiddleware all apphook urls are language namespaced.
What this means:
To reverse the first url from above you would use something like this in your template:
{% url app_main %}
If you want to access the same url but in a different language use a langauge namespace:
{% url de:app_main %}
{% url en:app_main %}
{% url fr:app_main %}
If you want to add a menu to that page as well that may represent some views in your app add it to your apphook like this:
from myapp.menu import MyAppMenu
class MyApphook(CMSApp):
name = _("My Apphook")
urls = ["myapp.urls"]
menus = [MyAppMenu]
apphook_pool.register(MyApphook)
For an example if your app has a Category model and you want this category model to be displayed in the menu when you attach the app to a page. We assume the following model:
from django.db import models
from django.core.urlresolvers import reverse
import mptt
class Category(models.Model):
parent = models.ForeignKey('self', blank=True, null=True)
name = models.CharField(max_length=20)
def __unicode__(self):
return self.name
def get_absolute_url(self):
return reverse('category_view', args=[self.pk])
try:
mptt.register(Category)
except mptt.AlreadyRegistered:
pass
It is encouraged to use django-mptt (a suitable version is included in the mptt directory) if you have data that is organized in a tree.
We would now create a menu out of these categories:
from menus.base import NavigationNode
from menus.menu_pool import menu_pool
from django.utils.translation import ugettext_lazy as _
from cms.menu_bases import CMSAttachMenu
from myapp.models import Category
class CategoryMenu(CMSAttachMenu):
name = _("test menu")
def get_nodes(self, request):
nodes = []
for category in Category.objects.all().order_by("tree_id", "lft"):
nodes.append(NavigationNode(category.name, category.pk, category.parent_id))
return nodes
menu_pool.register_menu(CategoryMenu)
If you add this menu now to your app-hook:
from myapp.menus import CategoryMenu
class MyApphook(CMSApp):
name = _("My Apphook")
urls = ["myapp.urls"]
menus = [MyAppMenu, CategoryMenu]
You get the static entries of MyAppMenu and the dynamic entries of CategoryMenu both attached to the same page.
If you want to display content of your apps on other pages custom plugins are a great way to accomplish that. For example, if you have a news app and you want to display the top 10 news entries on your homepage, a custom plugin is the way to go.
For a detailed explanation on how to write custom plugins please head over to the Custom Plugins section.