Search code examples
djangopython-3.xdjango-cms

Django-CMS Custom plugin and placeholders


I'm really new to Django-CMS, I had a look at the docs but I can;'t find what I need so I could be probably doing it wrong. Anyway I'm creating a custom plugin, I have the model with 3 placeholders inside:

models.py

class Tile(CMSPlugin):
   text = PlaceholderField('text', related_name='tile_text')
   img = PlaceholderField('img', related_name='tile_img')
   link = PlaceholderField('link', related_name='tile_link')

then I have 3 different Plugins using the model:

cms_plugins.py

from cms.plugin_base import CMSPluginBase
from cms.models.pluginmodel import CMSPlugin
from cms.plugin_pool import plugin_pool
from django.utils.translation import ugettext_lazy as _

from tiles_plugin.models import Tile


class BigTilePlugin(CMSPluginBase):
    model = Tile
    name = _('Big Tile Plugin')
    render_template = 'tiles_plugin/big_tile.html'
    allow_children = True

    def render(self, context, instance, placeholder):
        context['instance'] = instance
        return context

class MedTilePlugin(CMSPluginBase):
    model = Tile
    name = _('Medium Tile Plugin')
    render_template = 'tiles_plugin/med_tile.html'
    allow_children = True

    def render(self, context, instance, placeholder):
        context['instance'] = instance
        return context

class SmallTilePlugin(CMSPluginBase):
    model = Tile
    name = _('Small Tile Plugin')
    render_template = 'tiles_plugin/small_tile.html'
    allow_children = True

    def render(self, context, instance, placeholder):
        context['instance'] = instance
        return context


plugin_pool.register_plugin(BigTilePlugin)
plugin_pool.register_plugin(MedTilePlugin)
plugin_pool.register_plugin(SmallTilePlugin)

and then I have the templates:

big_tile.html

{% load cms_tags %}
<div class="big-tile">
    <div class="content">
        {% render_placeholder instance.text %}
    </div>
    <div class="link">
        {% render_placeholder instance.link %}
    </div>
    <div class="img">
        {% render_placeholder instance.img %}
    </div>
</div>

And here it comes the problem, when I create the plugin and i insert inside the text/picture/link plugins, these are not populated so basically everything is empty, it's like the javascript is not populating it (for sure it's not the javascript) but I think I'm missing the relationship with the child_plugins. Can anyone help me out?

Thanks

EDIT

This made it work properly:

    {% for plugin in instance.child_plugin_instances %}
        {% render_plugin plugin %}
    {% endfor %}

Thanks to @mfcovington


Solution

  • It looks like almost everything is right. However, to get text, for example, you need to use instance.tile.text instead of instance.text.

    So, your template should look something like this:

    {% load cms_tags %}
    <div class="big-tile">
        <div class="content">
            {% render_placeholder instance.tile.text %}
        </div>
        <div class="link">
            {% render_placeholder instance.tile.link %}
        </div>
        <div class="img">
            {% render_placeholder instance.tile.img %}
        </div>
    </div>
    

    Alternatively, when you set the context, you could set context['tile']:

    class BigTilePlugin(CMSPluginBase):
        ...
        def render(self, context, instance, placeholder):
            context['tile'] = instance.tile
            return context
    

    This would allow you to use tile.text, etc. instead of instance.tile.text, etc. in your template.

    EDIT:

    In case you are interested, besides your model info, there are lots of other things contained within instance. For example, in one of my cms_plugins.py files I added print(dir(instance)) within a CMSPlugin for a model called carousel and got the following output to my terminal (it will, of course differ from yours, but most things will be in common):

    ['DoesNotExist', 'Meta', 'MultipleObjectsReturned', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_base_manager', '_carousel_cache', '_check_column_name_clashes', '_check_field_name_clashes', '_check_fields', '_check_id_field', '_check_index_together', '_check_local_fields', '_check_m2m_through_same_relationship', '_check_managers', '_check_model', '_check_ordering', '_check_swappable', '_check_unique_together', '_db_connection', '_default_manager', '_deferred', '_do_insert', '_do_update', '_get_FIELD_display', '_get_basepath', '_get_children_path_interval', '_get_database_connection', '_get_database_cursor', '_get_lastpos_in_path', '_get_next_or_previous_by_FIELD', '_get_next_or_previous_in_order', '_get_parent_path_from_path', '_get_path', '_get_pk_val', '_get_serializable_model', '_get_unique_checks', '_inc_path', '_inst', '_int2str', '_meta', '_perform_date_checks', '_perform_unique_checks', '_placeholder_cache', '_prepare_pos_var', '_prepare_pos_var_for_add_sibling', '_prepare_pos_var_for_move', '_process_foreign_keys', '_render_meta', '_save_parents', '_save_table', '_set_pk_val', '_state', '_str2int', '_valid_pos_for_add_sibling', '_valid_pos_for_move', '_valid_pos_for_sorted_add_sibling', '_valid_pos_for_sorted_move', 'add_child', 'add_root', 'add_sibling', 'add_url', 'alias_reference', 'aliaspluginmodel', 'alphabet', 'carousel', 'carousel_id', 'carouselplugin', 'changed_date', 'check', 'child_plugin_instances', 'clean', 'clean_fields', 'cmsplugin_ptr', 'cmsplugin_ptr_id', 'cmsplugin_set', 'column', 'copy_plugin', 'copy_relations', 'copy_url', 'creation_date', 'date_error_message', 'delete', 'delete_url', 'depth', 'dump_bulk', 'edit_url', 'file', 'find_problems', 'fix_tree', 'flash', 'full_clean', 'gap', 'get_ancestors', 'get_annotated_list', 'get_breadcrumb', 'get_breadcrumb_json', 'get_children', 'get_children_count', 'get_database_vendor', 'get_depth', 'get_descendant_count', 'get_descendants', 'get_descendants_group_count', 'get_first_child', 'get_first_root_node', 'get_first_sibling', 'get_foreign_keys', 'get_instance_icon_alt', 'get_instance_icon_src', 'get_last_child', 'get_last_root_node', 'get_last_sibling', 'get_media_path', 'get_next_by_changed_date', 'get_next_by_creation_date', 'get_next_sibling', 'get_parent', 'get_plugin_class', 'get_plugin_class_instance', 'get_plugin_instance', 'get_plugin_name', 'get_position_in_placeholder', 'get_prev_sibling', 'get_previous_by_changed_date', 'get_previous_by_creation_date', 'get_root', 'get_root_nodes', 'get_short_description', 'get_siblings', 'get_sorted_pos_queryset', 'get_translatable_content', 'get_tree', 'googlemap', 'has_change_permission', 'id', 'inheritpageplaceholder', 'is_child_of', 'is_descendant_of', 'is_leaf', 'is_root', 'is_sibling_of', 'language', 'link', 'load_bulk', 'move', 'move_url', 'multicolumns', 'node_order_by', 'notify_on_autoadd', 'notify_on_autoadd_children', 'num_children', 'numchild', 'numconv_obj', 'numconv_obj_', 'objects', 'page', 'parent', 'parent_id', 'path', 'picture', 'pk', 'placeholder', 'placeholder_id', 'placeholderreference', 'plugin_type', 'position', 'post_copy', 'prepare_database_save', 'reload', 'render_plugin', 'save', 'save_base', 'serializable_value', 'set_base_attr', 'set_translatable_content', 'shinyapppluginmodel', 'steplen', 'teaser', 'text', 'translatable_content_excluded_fields', 'unique_error_message', 'validate_unique', 'video']