Renderer (feincms3.renderer)

class feincms3.renderer.TemplatePluginRenderer(regions_class=<class 'feincms3.renderer.Regions'>)[source]

This renderer allows registering functions, templates and context providers for plugins. It also supports rendering plugins’ templates using the rendering context of the surrounding template without explicitly copying required values into the local rendering context.


Return a list of all registered plugins, and is most useful when passed directly to one of django-content-editor’s contents utilities:

page = get_object_or_404(Page, ...)
contents = contents_for_item(page, renderer.plugins())
regions(self, item, *, inherit_from=None, regions=None)[source]

Return a Regions instance which lazily wraps the contents_for_item call. This is especially useful in conjunction with the render_region template tag. The inherit_from argument is directly forwarded to contents_for_item to allow regions with inherited content.

The Regions type may be overridden by passing a regions_class keyword argument when instantiating the TemplatePluginRenderer or by setting the regions argument of this method.

register_string_renderer(plugin, renderer)[source]

Register a rendering function which is passed the plugin instance and returns a HTML string:

    lambda plugin: mark_safe(plugin.text),
register_template_renderer(self, plugin, template_name, context=default_context)[source]

Register a renderer for plugin using a template. The template uses the same mechanism as {% include %} meaning that the full template context is available to the plugin renderer.

template_name can be one of:

  • A template path
  • A list of template paths
  • An object with a render method
  • A callable receiving the plugin as only parameter and returning any of the above.

context must be a callable receiving the plugin instance and the template context and returning a dictionary. The default implementation simply returns a dictionary containing a single key named plugin containing the plugin instance.

# Template snippets have access to everything in the template
# context, including for example ``page``, ``request``, etc.
    lambda plugin: plugin.template_name,

# Additional context can be provided:
    'pages/plugins/team.html',  # Can also be a callable
    lambda plugin, context: {
        'persons': Person.objects.filter(
            # Assuming that the page has a team foreign key:
render_plugin_in_context(plugin, context=None)[source]

Render a plugin, passing on the template context into the plugin’s template (if the plugin uses a template renderer).


Decorator for Regions.render methods implementing caching behavior

This decorator consumes the timeout keyword argument to the render method.

feincms3.renderer.default_context(plugin, context)[source]

Return the default context for plugins rendered with a template, which simply is a single variable named plugin containing the plugin instance.

class feincms3.renderer.Regions(item, *, contents, renderer)[source]

Wrapper for a content_editor.contents.Contents instance with support for caching the potentially somewhat expensive plugin loading and rendering step.

A view using this facility would look as follows:

def page_detail(request, slug):
    page = get_object_or_404(Page, slug=slug)
    return render(request, 'page.html', {
        'page': page,
        'regions': renderer.regions(
            # Optional:
            # Optional too:
        # Note! No 'contents' and no 'renderer' necessary in the
        # template.

The template itself should contain the following snippet:

{% load feincms3_renderer %}

{% block content %}

<h1>{{ page.title }}</h1>
  {% render_region regions "main" timeout=60 %}
  {% render_region regions "sidebar" timeout=60 %}

{% endblock %}

Caching is, of course, completely optional. When you’re caching regions though you should probably cache them all, because accessing the content of a single region loads the content of all regions. (It might still make sense if the rendering is the expensive part, not the database access.)


You should probably always let the renderer instantiate this class and not depend on the API, especially since the lazyness happens in the renderer, not in the Regions instance.


Return a cache key suitable for the given region passed

render(self, region, context=None, *, timeout=None)[source]

Render a single region using the context passed

If timeout is None caching is disabled.

feincms3.templatetags.feincms3_renderer.render_plugin(context, plugin)[source]

Render a single plugin. Requires the feincms3.renderer.TemplatePluginRenderer instance in the context as renderer:

{% render_plugin plugin %}

In general you should prefer render_region() over this tag.

feincms3.templatetags.feincms3_renderer.render_plugins(context, plugins)[source]

Render a list of plugins. Requires the feincms3.renderer.TemplatePluginRenderer instance in the context as renderer:

{% render_plugins plugins %}

This plugin is equivalent to:

{% for plugin in plugins %}{% render_plugin plugin %}{% endfor %}

In general you should prefer render_region() over this tag.

feincms3.templatetags.feincms3_renderer.render_region(context, regions, region, **kwargs)[source]

Render a single region. See Regions for additional details. Any and all keyword arguments are forwarded to the render method of the Regions instance.


{% render_region regions "main" %}


{% render_region regions "main" timeout=15 %}

The main advantage of Regions and render_region is that regions only lazily load plugins when needed, which means that caching also avoids the related database queries.