In this tutorial we’re going to take a Django poll app and integrate it intoœ the CMS.
Install the application from its GitHub repository using pip -e - this also places it in your virtualenv’s src directory as a cloned Git repository:
pip install -e git+http://git@github.com/divio/django-polls.git#egg=django-polls
You should end up with a folder structure similar to this:
env/
src/
django-polls/
polls/
__init__.py
admin.py
models.py
templates/
tests.py
urls.py
views.py
Let’s add it this application to our project. Add 'polls' to the end of INSTALLED_APPS in your project’s settings.py.
Add the following line to urlpatterns in the project’s urls.py:
url(r'^polls/', include('polls.urls', namespace='polls')),
Make sure this line is included before the line for the django-cms urls:
url(r'^', include('cms.urls')),
django CMS’s URL pattern needs to be last, because it “swallows up” anything that hasn’t already been matched by a previous pattern.
Now run the application’s migrations using south:
python manage.py migrate polls
At this point you should be able to add create polls and choices in the Django admin - localhost:8000/admin/ - and fill them in at /polls/.
However, in pages of the polls application we only have minimal templates, and no navigation or styling. Let’s improve this by overriding the polls application’s base template.
add my_site/templates/polls/base.html:
{% extends 'base.html' %}
{% block content %}
{% block polls_content %}
{% endblock %}
{% endblock %}
Open the /polls/ again. The navigation should be visible now.
So now we have integrated the standard polls app in our project. But we’ve not done anything django CMS specific yet.
If you’ve played around with the CMS for a little, you’ve probably already encountered CMS Plugins. They are the objects you can place into placeholders on your pages through the frontend: “Text”, “Image” and so forth.
We’re now going to extend the django poll app so we can embed a poll easily into any CMS page. We’ll put this integration code in a separate package in our project.
This allows integrating 3rd party apps without having to fork them. It would also be possible to add this code directly into the django-polls app to make it integrate out of the box.
Create a new package at the project root called polls_plugin:
python manage.py startapp polls_plugin
So our workspace looks like this:
env/
src/ # the django polls application is in here
polls_plugin/ # the newly-created application
__init__.py
admin.py
models.py
tests.py
views.py
my_site/
static/
project.db
requirements.txt
In your poll application’s models.py add the following:
from django.db import models from cms.models import CMSPlugin from polls.models import Poll
- class PollPlugin(CMSPlugin):
poll = models.ForeignKey(Poll)
- def __unicode__(self):
- return self.poll.question
Note
django CMS plugins inherit from cms.models.CMSPlugin (or a subclass thereof) and not models.Mod el.
Now create a file cms_plugins.py in the same folder your models.py is in. The plugin class is responsible for providing django CMS with the necessary information to render your plugin.
For our poll plugin, we’re going to write the following plugin class:
from cms.plugin_base import CMSPluginBase from cms.plugin_pool import plugin_pool from djangocms_polls.models import PollPlugin from django.utils.translation import ugettext as _
- class CMSPollPlugin(CMSPluginBase):
model = PollPlugin # model where plugin data are saved module = _(“Polls”) name = _(“Poll Plugin”) # name of the plugin in the interface render_template = “djangocms_polls/poll_plugin.html”
- def render(self, context, instance, placeholder):
- context.update({‘instance’: instance}) return context
plugin_pool.register_plugin(CMSPollPlugin) # 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.
The convention for plugin naming is as follows:
You don’t need to follow this, but it’s a sensible thing to do.
The render_template attribute in the plugin class is required, and tells the plugin which render_template to use when rendering.
In this case the template needs to be at polls_plugin/templates/djangocms_polls/poll_plugin.html and 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_text }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>
Now add djangocms_polls to INSTALLED_APPS and create a database migration to add the plugin table (using South):
python manage.py schemamigration polls_plugin –init python manage.py migrate polls_plugin
Finally, start the runserver and visit http://localhost:8000/.
You can now drop the Poll Plugin into any placeholder on any page, just as you would any other plugin.
Next we’ll integrate the Polls application more fully into our django CMS project.