Plugins

Our application exists and is installed, but so far, does absolutely nothing at all. In this section we’ll add some new functionality: a Polls plugin.

The Plugin model

In the models.py of polls_cms_integration add the following:

  1. from django.db import models
  2. from cms.models import CMSPlugin
  3. from polls.models import Poll
  4. class PollPluginModel(CMSPlugin):
  5. poll = models.ForeignKey(Poll)
  6. def __unicode__(self):
  7. return self.poll.question

Note

django CMS plugins inherit from cms.models.CMSPlugin (or a sub-class thereof) and not models.Model.

PollPluginModel might seem an odd choice for a model name (that is, with model in the name) but it helps distinguish it from the next class, PollPluginPublisher, that we need to create.

The Plugin class

Now create a new 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:

  1. from cms.plugin_base import CMSPluginBase
  2. from cms.plugin_pool import plugin_pool
  3. from polls_cms_integration.models import PollPluginModel
  4. from django.utils.translation import ugettext as _
  5. class PollPluginPublisher(CMSPluginBase):
  6. model = PollPluginModel # model where plugin data are saved
  7. module = _("Polls")
  8. name = _("Poll Plugin") # name of the plugin in the interface
  9. render_template = "polls_cms_integration/poll_plugin.html"
  10. def render(self, context, instance, placeholder):
  11. context.update({'instance': instance})
  12. return context
  13. plugin_pool.register_plugin(PollPluginPublisher) # 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.

A reasonable convention for plugin naming is:

  • PollPluginModel: the model class
  • PollPluginPublisher: the plugin class

You don’t need to follow this convention, but choose one that makes sense and stick to it.

The template

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_cms_integration/templates/polls_cms_integration/poll_plugin.html and should look something like this:

  1. <h1>{{ instance.poll.question }}</h1>
  2. <form action="{% url 'polls:vote' instance.poll.id %}" method="post">
  3. {% csrf_token %}
  4. <div class="form-group">
  5. {% for choice in instance.poll.choice_set.all %}
  6. <div class="radio">
  7. <label>
  8. <input type="radio" name="choice" value="{{ choice.id }}">
  9. {{ choice.choice_text }}
  10. </label>
  11. </div>
  12. {% endfor %}
  13. </div>
  14. <input type="submit" value="Vote" />
  15. </form>

Prepare the database

Create a database migration to add the plugin table:

  1. python manage.py makemigrations polls_cms_integration
  2. python manage.py migrate polls_cms_integration

Try out the new 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.

the 'Poll plugin' in the plugin selector