From this point onwards, this tutorial assumes you have done the Django Tutorial (for Django 1.6) and will show you how to integrate the tutorial’s poll app into the django CMS. Hereafter, if a poll app is mentioned, we are referring to the one you get after completing the Django Tutorial. Also, make sure the poll app is in your INSTALLED_APPS.
We assume your main urls.py looks something like this:
# -*- coding: utf-8 -*-
from django.conf.urls import *
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^admin/', include(admin.site.urls)),
(r'^polls/', include('polls.urls', namespace='polls')),
(r'^', include('cms.urls')),
)
A Plugin is a small bit of content that you can place on your pages.
For our polling app we would like to have a small poll plugin which shows a poll and lets the user vote.
In your poll application’s models.py add the following:
# -*- coding: utf-8 -*-
from django.db import models
from cms.models import CMSPlugin
# existing Poll and Choice models...
....
class PollPluginModel(CMSPlugin):
poll = models.ForeignKey('polls.Poll', related_name='plugins')
def __unicode__(self):
return self.poll.question
Note
django CMS plugins must inherit from cms.models.CMSPlugin (or a subclass thereof) and not models.Model.
Run manage.py syncdb to create the database tables for this model or see Using South with django CMS to see how to do it using South.
Now create a file cms_plugins.py in the same folder your models.py is in. After having followed the Django Tutorial and adding this file your polls app folder should look like this:
polls/
templates/
polls/
detail.html
index.html
results.html
__init__.py
admin.py
cms_plugins.py
models.py
tests.py
urls.py
views.py
The plugin class is responsible for providing the django CMS with the necessary information to render your Plugin.
For our poll plugin, write the following plugin class:
# -*- coding: utf-8 -*-
from django.utils.translation import ugettext as _
from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool
from .models import PollPluginModel
class PollPlugin(CMSPluginBase):
model = PollPluginModel # Model where data about this plugin is saved
name = _("Poll Plugin") # Name of the plugin
render_template = "polls/plugin.html" # template to render the plugin with
def render(self, context, instance, placeholder):
context.update({'instance':instance})
return context
plugin_pool.register_plugin(PollPlugin) # register the plugin
Note
All plugin classes must inherit from cms.plugin_base.CMSPluginBase and must register themselves with the cms.plugin_pool.plugin_pool.
You probably noticed the render_template attribute in the above plugin class. In order for our plugin to work, that template must exist and is responsible for rendering the plugin. You should create a new file in your poll-app’s templates folder under polls called plugin.html.
The template should look something like this:
<h1>{{ instance.poll.question }}</h1>
<form action="{% url 'polls:vote' instance.poll.id %}" method="post">
{% csrf_token %}
{% for choice in instance.poll.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
<label for="choice{{ forloop.counter }}">{{ choice.choice }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>
Note
We don’t show the errors here, because when submitting the form you’re taken off this page to the actual voting page.
Right now, external apps are statically hooked into the main urls.py. This is not the preferred approach in the django CMS. Ideally you attach your apps to CMS pages. This will allow the editors to move your page, and the attached application to different parts of the page tree, without breaking anything.
For that purpose you write a CMSApp. That is just a small class telling the CMS how to include that app.
CMS Apps live in a file called cms_app.py, so go ahead and create it to make your polls app look like this:
polls/
templates/
polls/
detail.html
index.html
plugin.html
results.html
__init__.py
admin.py
cms_app.py
cms_plugins.py
models.py
tests.py
urls.py
views.py
In this file, write:
# -*- coding: utf-8 -*-
from django.utils.translation import ugettext_lazy as _
from cms.app_base import CMSApp
from cms.apphook_pool import apphook_pool
class PollsApp(CMSApp):
name = _("Poll App") # give your app a name, this is required
urls = ["polls.urls"] # link your app to url configuration(s)
app_name = "polls" # this is the application namespace
apphook_pool.register(PollsApp) # register your app
NOTE: If your polls module is not in the root of your project folder, then you may need to adjust the line above urls = ["polls.urls"] accordingly.
Now remove the inclusion of the polls urls in your main urls.py so it looks like this:
# -*- coding: utf-8 -*-
from django.conf.urls import *
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
(r'^admin/', include(admin.site.urls)),
# delete the polls entry that was here, no longer needed!
(r'^', include('cms.urls')),
)
Restart your server so that the PollsApp will now register.
Now open your Django Admin in your browser and navigate to the CMS app, then choose Pages. This should display the “page tree”. From this page, create a page called “Polls”. Save the page with the button: “Save and continue editing”. Next, press “Advanced Settings” and choose “Poll App” in the drop- down menu labeled “Application”. Finally, in the field named “Application instance name”, enter “polls” and “Save”.
Unfortunately, for these changes to take effect, you will have to restart your server (this is automatic when using runserver, but not other servers). So do that and afterwards if you navigate to that CMS Page, you will see your polls application.