Custom Plugins

Suppose you have the following gallery model:

class Gallery(models.Model):
        name = models.CharField(max_length=30)

class Picture(models.Model):
        gallery = models.ForeignKey(Gallery)
        image = models.ImageField(upload_to="uploads/images/")
        description = models.CharField(max_length=60)

And that you want to display this gallery between two text blocks. You can do this with a CMS plugin. To create a CMS plugin you need two components: a CMSPlugin model and a cms_plugins.py file.

Plugin Model

First create a model that links to the gallery via a ForeignKey field:

from cms.models import CMSPlugin

class GalleryPlugin(CMSPlugin):
        gallery = models.ForeignKey(Gallery)

Be sure that your model inherits the CMSPlugin class. The plugin model can have any fields it wants. They are the fields that get displayed if you edit the plugin.

cms_plugins.py

After that create in the application folder (the same one where models.py is) a cms_plugins.py file.

In there write the following:

from cms.plugin_base import CMSPluginBase
from cms.plugin_pool import plugin_pool
from models import GalleryPlugin
from django.utils.translation import ugettext as _

class CMSGalleryPlugin(CMSPluginBase):
        model = GalleryPlugin
        name = _("Gallery")
        render_template = "gallery/gallery.html"

        def render(self, context, instance, placeholder):
                context.update({'gallery':instance.gallery,
                                                'object':instance,
                                                'placeholder':placeholder})
                return context

plugin_pool.register_plugin(CMSGalleryPlugin)

model

Is the CMSPlugin model we created earlier. If you don’t need a model because you just want to display some template logic, use CMSPlugin from cms.models as the model instead.

name

Will be displayed in the plugin editor

render_template

Will be rendered with the context returned by the render function

render

The render function takes 3 arguments:

*context*:

The context of the template placeholder was placed.

*instance*:

The instance of the GalleryPlugin model

*placeholder*:

The name of the placeholder this plugin appears. It is normally a good idea to give the placeholder to the template so you can style the content differently in the template based on which placeholder it is placed.

If you want to process forms in the render function or if you want to see if the user is logged in you may want to access the request. You can accomplish this simply with:

request = context['request']

Because the request will always be in the context as the requestcontext processor is required by the CMS.

Template

Now create a gallery.html template in templates/gallery/ and write the following in there.

{% for image in gallery.picture_set.all %}
        <img src="{{ image.image.url }}" alt="{{ image.description }}" />
{% endfor %}

Now go into the admin create a gallery and afterwards go into a page and add a gallery plugin and some pictures should appear in your page.

Limiting Plugins per Placeholder

You can limit in which placeholder certain plugins can appear. Add a CMS_PLACEHOLDER_CONF to your settings.py.

Example:

CMS_PLACEHOLDER_CONF = {
        'content': {
                "plugins": ('ContactFormPlugin','FilePlugin','FlashPlugin','LinkPlugin','PicturePlugin','TextPlugin'),
                "extra_context": {"theme":"16_16"},
                "name": gettext("content")
        },

        'right-column': {
                "plugins": ('ContactFormPlugin','TextPlugin', 'SimpleGalleryPublicationPlugin'),
        "extra_context": {"theme":"16_5"},
                "name": gettext("right column")
        },

content” and “right-column” are the names of two placeholders. The plugins list are filled with Plugin class names you find in the cms_plugins.py. You can add extra context to each placeholder so plugin-templates can react to them. In this example we give them some parameters that are used in a CSS Grid Framework. You can change the displayed name in the admin with the name parameter. In combination with gettext you can translate this names according to the language of the user.

Advanced

CMSGalleryPlugin can be even further customized:

Because CMSPluginBase extends ModelAdmin from django.contrib.admin you can use all the things you are used to with normal admin classes. You can defined inlines, the form, the form template etc.

Note: If you want to overwrite the form be sure to extend from admin/cms/page/plugin_change_form.html to have an unified look across the plugins and to have the preview functionality automatically installed.

Questions/Feedback

If you notice errors with this documentation, please open a ticket and let us know!

Please only use the ticket tracker for criticisms and improvements on the docs. For tech support, ask in the IRC channel or post to the django-cms mailing-list.