Plugins

In this tutorial we’re going to take a basic Django opinion poll application and integrate it into the CMS.

Create a plugin model

In the models.py of polls_cms_integration add the following:

fromdjango.dbimport models
fromcms.modelsimport CMSPlugin
frompolls.modelsimport Poll
classPollPluginModel(CMSPlugin):
 poll = models.ForeignKey(Poll, on_delete=models.CASCADE)
 def__str__(self):
 return self.poll.question

This creates a plugin model class; these all inherit from the cms.models.pluginmodel.CMSPlugin base class.

Note

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

Create and run migrations:

pythonmanage.pymakemigrationspolls_cms_integration
pythonmanage.pymigratepolls_cms_integration

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:

fromcms.plugin_baseimport CMSPluginBase
fromcms.plugin_poolimport plugin_pool
frompolls_cms_integration.modelsimport PollPluginModel
fromdjango.utils.translationimport gettext as _
@plugin_pool.register_plugin # register the plugin
classPollPluginPublisher(CMSPluginBase):
 model = PollPluginModel # model where plugin data are saved
 module = _("Polls")
 name = _("Poll Plugin") # name of the plugin in the interface
 render_template = "polls_cms_integration/poll_plugin.html"
 defrender(self, context, instance, placeholder):
 context.update({"instance": instance})
 return context

Note

All plugin classes must inherit from cms.plugin_base.CMSPluginBase and must register themselves with the plugin_pool.

A reasonable convention for plugin naming is:

  • PollPluginModel: the model class

  • PollPluginPublisher: the plugin class

A second convention is also countered quite frequently:

  • Poll: the model class

  • PollPlugin: the plugin class

You don’t need to follow either of those 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:

<h1>{{ instance.poll.question }}</h1>
<form action="{% url 'polls:vote' instance.poll.id %}" method="post">
 {% csrf_token %}
 <div class="form-group">
 {% for choice in instance.poll.choice_set.all %}
 <div class="radio">
 <label>
 <input type="radio" name="choice" value="{{ choice.id }}">
 {{ choice.choice_text }}
 </label>
 </div>
 {% endfor %}
 </div>
 <input type="submit" value="Vote" />
</form>

Test the plugin

Now you can restart the runserver (required because you added the new cms_plugins.py file, 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

Next we’ll integrate the Polls application more fully into our django CMS project.