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:
- https://groups.google.com/forum/#!topic/django-cms/WDUjIpSc23c/discussion
- https://groups.google.com/forum/#!msg/django-cms/iAuZmft5JNw/yPl8NwOtQW4J
- https://groups.google.com/forum/?fromgroups=#!topic/django-cms/QeTlmxQnn3E
- https://groups.google.com/forum/#!topic/django-cms/2mWvEpTH0ns/discussion
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 %}
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 %}
- Django/Webpack – How to serve generated webpack bundles with webpack dev server
- Adding static() to urlpatterns only work by appending to the list
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 %}
- Django translate model choices
- Logging Django SQL queries with DEBUG set to False
- Determine if Django is running under the development server
- Django countries encoding is not giving correct name
- Celery: launch task on start
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.
1👍
2023 update
Accepted answer https://stackoverflow.com/a/17148137/5322302 has issues with latest DjangoCMS.
Updated solution (credits for F.B. from DjangoCMS community).
Tested with Django CMS 4.
{% load get_placeholder %}
...
{% get_placeholder "content" as placeholder_content %}
{% if placeholder_content %}
<div class="my-2">{{ placeholder_content }}</div>
{% endif %}
code of the templatetag .../templatetags/get_placeholder.py
from classytags.arguments import Argument, MultiValueArgument
from classytags.values import StringValue
from django import template
from django.utils.safestring import mark_safe
from cms.models.placeholdermodel import Placeholder as PlaceholderModel
from cms.templatetags.cms_tags import (
DeclaredPlaceholder,
Placeholder,
PlaceholderOptions,
)
register = template.Library()
class RenderGetPlaceholder(Placeholder):
"""
Render the content of a placeholder to a variable. Can be provided
with the name of the placholder (i.e. "Header" in the case of a normal
CMS page) or a template variable containing a placeholder (i.e. myentry.content in the
case of an external app using a placeholder)
{% get_placeholder ["string"|placeholder_var] as variable_name %}
e.g.
{% load extra_cms_tags %}
{% get_placeholder "My Placeholder" as my_placeholder %}
{% if my_placeholder %}
<div>
{{ my_placeholder }}
</div>
{% endif %}
"""
name = "get_placeholder"
options = PlaceholderOptions(
Argument("name", resolve=True),
MultiValueArgument("extra_bits", required=False, resolve=False),
"as",
Argument("varname", resolve=False, required=True),
blocks=[
("endplaceholder", "nodelist"),
],
)
def render_tag(self, context, name, extra_bits, varname, nodelist=None):
if isinstance(name, PlaceholderModel):
content = name.render(context, None)
else:
content = super(RenderGetPlaceholder, self).render_tag(context, name, extra_bits, nodelist)
context[varname] = mark_safe(content)
return ""
def get_declaration(self):
# Fix some template voodoo causing errors
slot = self.kwargs["name"].var.var.__str__().strip('"').strip("'")
return DeclaredPlaceholder(slot=slot, inherit=False)
register.tag(RenderGetPlaceholder)
- Django: How to display Validation errors not specific to a field?
- How does a .env file relate to Python / Django?
- How to achieve authentication with django-auth-ldap?
- Handling HTTP chunked encoding with django
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
- Error decoding signature in Django Rest Framework
- Django class based views – UpdateView with two model forms – one submit
- Django or Ruby on Rails
- How to store google oauth token in django : Storage or database
- Django: foreign key value in a list display admin
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 %}