Skip to content

Instantly share code, notes, and snippets.

@mkoistinen
Last active August 29, 2015 14:15
Show Gist options
  • Save mkoistinen/3c2447ba4dc79d440122 to your computer and use it in GitHub Desktop.
Save mkoistinen/3c2447ba4dc79d440122 to your computer and use it in GitHub Desktop.
TemplateTag: render_model_add_block
# templatetag: render_model_add_block
## Description
Currently django CMS has a templatetag: render_model_add, which is used like this: `{% render_model_add mymodel_instance %}`. Which then renders an icon of a "plus" symbol onto the page. This plus symbol is bound to a double-click handler which, which double-clicked, renders a modal dialog for creating a new instance of the model that `mymodel_instances` was created from.
This is great, but offers limited flexibility when creating front-end operator UX for projects.
This re-implementation is extremely similar, but instead of linking the modal dialog add-form to a plus icon, it allows the developer to wrap any arbitrary content. This could be as simple as text, but could also be a generic representation of the type of content that the operator wishes to create.
Very useful.
This has been submitted as a PR to the django CMS project, but, if accepted, wouldn't be available until version 3.1 or later. So, this code here is sort of like `from __future__ import ...` =)
## Installation
1. In your project, create a new app called "future", and add these two files in their appropriate places:
````
future
__init__.py
templates
cms
toolbar
plugin.html <---- plugin.html goes here
templatetags
future_tags.py <--- future_tags.py goes here here
````
1. Next, add this new "future" app to your INSTALLED_APPS
1. Finally, since this implementation uses as much of the existing CMS code as possible, we need to tell your configuration to use *this* implmentation of plugin.html and not the normal one from your cms installation. So, in your settings add something like:
````
TEMPLATE_DIRS = (
os.path.join(PROJECT_PATH, "apps/future/templates"), <---- add something like this before the existing line
os.path.join(PROJECT_PATH, "templates"),
)
````
## Usage
In your template, instead of using `{% render_model_add mymodel_instance %}`, use something like:
````
{% load future_tags ... %}
{% render_model_add_block mymodel_instance %}<div class="whatever"><img src="generic_sample.png"></div>{% endrender_model_add_block %}
````
# -*- coding: utf-8 -*-
from django import template
from django.template.loader import render_to_string
from django.utils.safestring import mark_safe
from cms.templatetags.cms_tags import CMSEditableObject
from classytags.arguments import Argument
from classytags.core import Options
register = template.Library()
class CMSEditableObjectAddBlock(CMSEditableObject):
"""
Templatetag that links arbitrary content to the addform for the specified
model (based on the provided model instance).
"""
name = 'render_model_add_block'
options = Options(
Argument('instance'),
Argument('language', default=None, required=False),
Argument('view_url', default=None, required=False),
Argument('view_method', default=None, required=False),
'as',
Argument('varname', required=False, resolve=False),
blocks=[('endrender_model_add_block', 'nodelist')],
)
def render_tag(self, context, **kwargs):
"""
Renders the block and then inject the resulting HTML in the template
context
"""
context.push()
template = self.get_template(context, **kwargs)
data = self.get_context(context, **kwargs)
data['content'] = mark_safe(kwargs['nodelist'].render(data))
data['rendered_content'] = data['content']
output = render_to_string(template, data)
context.pop()
if kwargs.get('varname'):
context[kwargs['varname']] = output
return ''
else:
return output
def get_context(self, context, instance, language,
view_url, view_method, varname, nodelist):
"""
Uses _get_empty_context and adds the `render_model_icon` variable.
"""
extra_context = self._get_empty_context(context, instance, None,
language, view_url, view_method,
editmode=False)
extra_context['render_model_add'] = True
return extra_context
register.tag(CMSEditableObjectAddBlock)
{% spaceless %}{% load i18n l10n sekizai_tags static cms_tags %}
<div class="cms_plugin cms_plugin-{% if generic %}{{ generic.app_label }}-{{ generic.module_name }}-{% if attribute_name %}{{ attribute_name|slugify }}-{% endif %}{% endif %}{{ instance.pk|unlocalize }}{% if content %}{% elif render_model_icon %} cms_render_model_icon{% elif render_model %} cms_render_model{% elif render_model_block %} cms_render_model cms_render_model_block{% elif render_model_add %} cms_render_model_add{% endif %}">{% if content %}{{ content }}{% elif render_model_icon %}<img src="{% static 'cms/img/toolbar/render_model_placeholder.png' %}">{% elif render_model_add %}<img src="{% static 'cms/img/toolbar/render_model_placeholder.png' %}">{% else %}{{ rendered_content }}{% endif %}</div>
{% addtoblock "js" %}
<script>
(function($) {
// CMS.$ will be passed for $
$(document).ready(function () {
new CMS.Plugin('cms_plugin-{% if generic %}{{ generic.app_label }}-{{ generic.module_name }}-{% if attribute_name %}{{ attribute_name|slugify }}-{% endif %}{% endif %}{{ instance.pk|unlocalize }}', {
'type': {% if generic %}'generic'{% else %}'plugin'{% endif %},
'page_language': '{{ LANGUAGE_CODE }}',
'placeholder_id': '{{ instance.placeholder_id|unlocalize }}',
'plugin_name': '{{ instance.get_plugin_name|default:"" }}',
'plugin_type': '{{ instance.plugin_type }}',
'plugin_id': '{{ instance.pk|unlocalize }}',
'plugin_language': '{{ instance.language|default:"" }}',
'plugin_parent': '{{ instance.parent_id|unlocalize }}',
'plugin_order': '{{ instance.plugin_order }}',{% language request.toolbar.toolbar_language %}
'plugin_breadcrumb': {{ instance.get_breadcrumb_json|default:"[]" }},
'plugin_restriction': [{% for cls in allowed_child_classes %}"{{ cls }}"{% if not forloop.last %},{% endif %}{% endfor %}],
'onClose': {% if refresh_page %}'REFRESH_PAGE'{% else %}{% if redirect_on_close %}'{{ redirect_on_close }}'{% else %}false{% endif %}{% endif %},
'urls': {
'add_plugin': '{% if add_url %}{{ add_url }}{% else %}{% cms_admin_url "cms_page_add_plugin" %}}{% endif %}',
'edit_plugin': '{% if edit_url %}{{ edit_url }}{% elif instance %}{% cms_admin_url "cms_page_edit_plugin" instance.pk %}{% endif %}',
'move_plugin': '{% if move_url %}{{ move_url }}{% else %}{% cms_admin_url "cms_page_move_plugin" %}{% endif %}',
'delete_plugin': '{% if delete_url %}{{ delete_url }}{% elif instance %}{% cms_admin_url "cms_page_delete_plugin" instance.pk %}{% endif %}',
'copy_plugin': '{% cms_admin_url "cms_page_copy_plugins" %}'
} {% endlanguage %}
});
});
})(CMS.$);
</script>{% endaddtoblock %}
{% endspaceless %}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment