11

I use:

  • DjangoCMS 2.4
  • Django 1.5.1
  • Python 2.7.3

I would like to check if my placeholder is empty.

<div>
    {% placeholder "my_placeholder" or %}
    {% endplaceholder %}
</div>

I don't want the html between the placeholder to be created if the placeholder is empty.

{% if placeholder "my_placeholder" %}
<div>
    {% placeholder "my_placeholder" or %}
    {% endplaceholder %}
</div>
{% endif %}
daiuto
  • 486
  • 2
  • 10
  • 20
21S
  • 351
  • 3
  • 11

6 Answers6

18

There is no built-in way to do this at the moment in django-cms, so you have to write a custom template tag. There are some old discussions about this on the django-cms Google Group:

Based on the code in the first discussion, I've put together the following Gist:

I use it like so:

{% load extra_cms_tags %}
{% get_placeholder "My Placeholder" as my_placeholder %}

{% if my_placeholder %}
<div>
    {{ my_placeholder }}
</div>
{% endif %}
Timmy O'Mahony
  • 53,000
  • 18
  • 155
  • 177
  • I'm a beginner. Where should have put the file ? – 21S Jun 17 '13 at 13:18
  • 4
    It's a template tag so you have to create a folder called `templatetags` in one of your applications, create a file (`extra_cms_tags.py` for example) then in your template call `{% load extra_cms_tags %}` to import it – Timmy O'Mahony Jun 17 '13 at 13:30
  • 1
    Don't forget to add `__init__.py` to your `templatetags` folder ;). See [custom template-tags documentation](https://docs.djangoproject.com/en/1.7/howto/custom-template-tags/) for more details. – GabLeRoux Feb 15 '15 at 19:07
  • If you keep scrolling there's a better answer: https://stackoverflow.com/a/36098323/1605873 – Sebastián Vansteenkiste Dec 17 '19 at 19:39
6

If you want additional content to be displayed in case the placeholder is empty, use the or argument and an additional {% endplaceholder %} closing tag. Everything between {% placeholder "..." or %} and {% endplaceholder %} is rendered in the event that the placeholder has no plugins or the plugins do not generate any output.

Example:

{% placeholder "content" or %}

There is no content.

{% endplaceholder %}
Flimm
  • 136,138
  • 45
  • 251
  • 267
Ashish Gupta
  • 1,153
  • 12
  • 14
  • 1
    This should be the correct answer. Super simple and does not require template tags. – Sam Texas May 13 '16 at 14:30
  • 6
    This is great, but it doesn't let you output HTML content only if the placeholder is not empty. – Flimm Aug 15 '16 at 14:43
  • @Flimm I'm not sure in which version did you try and it didn't do that, but on `django-cms==3.4.6` it works like a charm: the content between the tags appears ONLY if the placeholder is empty. – Sebastián Vansteenkiste Dec 17 '19 at 19:38
5

Here's a very compact solution.

Template filter:

@register.filter('placeholder_is_empty')
def placeholder_is_empty(request, slot):
    page = request.current_page
    placeholder = page.placeholders.get(slot=slot)
    return placeholder.cmsplugin_set.exists()

Usage in template:

{% if request|placeholder_is_empty:'myplaceholder' %}
    <h1>Here comes some content... </h1>
{% endif %}
Philipp Zedler
  • 1,660
  • 1
  • 17
  • 36
3

Depending on what you are trying to achieve, you can simply use CSS to hide the element if doesn't have content using the :empty selector. And if you are worried about white spaces you can use Django's in-build {% spaceless %} template tag to remove them.

So you'd get this template:

{% spaceless %}
<div class="hide_if_empty">
    {% placeholder "my_placeholder" %}
</div>
{% endspaceless %}

And this CSS:

hide_if_empty:empty {
    display: none;
}

Not exactly what was asked for as it doesn't remove the HTML - but this will solve the most common case where one wants to check if a place holder is empty, and doesn't require the introduction of a new template tag.

Alice Heaton
  • 1,140
  • 11
  • 16
0

Based on the great answer form @Philip Zedler, a solution that works for both placeholder on django-cms pages, but also on placeholders "outside of the cms".

@register.filter()
def placeholder_empty(page_placeholder, slot=None):
    """
    for page/slot, pass a page object, and a slot name:  
    {% if request.current_page|djangocms_misc_placeholder_empty:"content" %}

    for a outside page placeholder, just the placeholder object:
    {% if object.placeholderfield|djangocms_misc_placeholder_empty %}

    also, with:
    {% with ph_empty=object.placeholderfield|djangocms_misc_placeholder_empty %}
    """
    placeholder = None
    if isinstance(page_placeholder, Placeholder):
        placeholder = page_placeholder
    elif isinstance(page_placeholder, Page):
        page = page_placeholder
        try:
            placeholder = page.placeholders.get(slot=slot)
        except Placeholder.DoesNotExist:
            pass
    if placeholder:
        # // return not placeholder.cmsplugin_set.filter(language=get_language()).exists()
        return not placeholder.cmsplugin_set.exists()
    return False

usage in template

{% if request.current_page|placeholder_empty:'content' %}
    <h1>Fallback!</h1>
{% endif %}

It's in my djangocms-misc package

benzkji
  • 1,718
  • 20
  • 41
0

I took the extra compact solution here and created a templatetag that checks if a static placeholder is not empty:

from cms.toolbar.utils import get_toolbar_from_request

@register.filter("static_placeholder_is_not_empty")
def static_placeholder_is_not_empty(request, slot):

    placeholder = StaticPlaceholder.objects.get(code=slot)

    if get_toolbar_from_request(request).edit_mode_active:
        placeholder = placeholder.draft
    else:
        placeholder = placeholder.public

    is_not_empty = len(placeholder.get_plugins(request.LANGUAGE_CODE)) > 0
    return is_not_empty

It's used like this:

{% load my_new_shiny_templatetag %}

{% if request|static_placeholder_is_not_empty:'my_static_placeholder' %}
  <div class="something">
{% endif %}

{% static_placeholder "my_static_placeholder" %}

{% if request|static_placeholder_is_not_empty:'my_static_placeholder' %}
  </div>
{% endif %}
sodimel
  • 864
  • 2
  • 11
  • 24