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 %}
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:
https://gist.github.com/timmyomahony/5796677
I use it like so:
{% load extra_cms_tags %}
{% get_placeholder "My Placeholder" as my_placeholder %}
{% if my_placeholder %}
<div>
{{ my_placeholder }}
</div>
{% endif %}
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 %}
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 %}
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.
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
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 %}
Related
I have a django app with a basic model (Job). Now in my template I would like to check if an instance exists of that model or not. I want to project a text if there is nothing yet to show, otherwise I'd like to show the model attributes.
Somehow like so (which obviously doesn't work):
{% if job.title != "" %}
{{ job.title }}
{% else %}
hola
{% endif %}
Also tried:
{% for job in jobs %}
{% if job.title %}
{{ job.title }}
{% else %}
Hola
{% endif %}
{% endfor %}
It makes sense it doesn't work because how can I loop through it or return something if it doesn't exist. Is there a simple way to even do that in a template? Or do I have to write my own function? Or what would be a way to do that?
Help is of course very much appreciated
You can use the {% if %} tag. As Django doc says:
The {% if %} tag evaluates a variable, and if that variable is “true” (i.e. exists, is not empty, and is not a false boolean value) the contents of the block are output.
So you can do something like this:
{% if job %}
{{ job.title }}
{% else %}
<p>Hi from Uruguay</p>
{% endif %}
If you need this inside a for, as #dirkgroten said, you need to use the {% empty %} tag. There is an example in the Django doc.
views.py:
def get(request):
p = Publisher.objects.filter(name='tux')
return render(request, 'main.html', {'items': p[0]})
main.html:
<html>
<body>
{{ items }}
<hr>
{% if 'tux' in items %}
<h1>this is tux</h1>
{% else %}
<h1>sorry!</h1>
{% endif %}
</body>
</html>
What is printed on the webpage:
tux
sorry!
And what about if I want to use {% ifequal %} tag?
What syntax should be used? I tried this:
{% ifequal {{items}} 'tux' %}
and it turned parse error, and I also tried this:
{% ifequal items 'tux' %}
but the result was again:
tux
sorry!
You cannot use it like this: {% if 'tux' in items %}, since items is an object.
Use {% if 'tux' in items.name %} instead.
The reason you get 'tux' displayed in the case of {{items}} is that your model returns name field as a unicode representation.
I have a weird situation with if statement in Django. It seems that django doesn't see it and I don't know why
my template file:
<div class="article-intro">
<p>{{ article.jezyk }} </p>
{% if article.jezyk = 'EN' %}
{% for sala in sala %}
<div>{{ sala }}</div>
{%endfor %}
{% endif %}
</div>
It looks like this:
As we see on the picture tag:
{{ article.jezyk }}
returns a value 'EN'
Why then "if statment" doesn't work? Is there any explanation?
My views.py
from django.shortcuts import render_to_response
from articles.models import Article
from sale.models import Sala
from godzina.models import Godzina
from jezyk.models import Jezyk
def articles(request):
return render_to_response('articles.html',{'articles' : Article.objects.all(),'godzina': Godzina.objects.all(),'sala': Sala.objects.order_by('jezyk') })
Once again you have not provided the information necessary to answer your question, ie the models. However we know from your previous questions that Article.jezyk is a ForeignKey. When you output a FK field in the template, it will print the result of the unicode method, but that doesn't mean they are actually equal. You need to compare the field itself, for example:
{% if article.jezyk.language = 'EN' %}
or whatever the field is on the Jezyk model that contains the language code.
try this ifequal :
e.g
{% ifequal article.jezyk 'EN' %}
<!-- Ur code -->
{% endifequal %}
use == operator
e.g.
{% if somevar == "x" %}
This appears if variable somevar equals the string "x"
{% endif %}
Documentation: link
Use other variable name in for loop. Same sala variable is used for iterator.
e.g.:
{% for i in sala %}
<div>{{ i }}</div>
{% endfor %}
I want to put break and continue in my code, but it doesn't work in Django template. How can I use continue and break using Django template for loop. Here is an example:
{% for i in i_range %}
{% for frequency in patient_meds.frequency %}
{% ifequal frequency i %}
<td class="nopad"><input type="checkbox" name="frequency-1" value="{{ i }}" checked/> {{ i }} AM</td>
{{ forloop.parentloop|continue }} ////// It doesn't work
{ continue } ////// It also doesn't work
{% endifequal %}
{% endfor%}
<td class="nopad"><input type="checkbox" name="frequency-1" value="{{ i }}"/> {{ i }} AM</td>
{% endfor %}
Django doesn't support it naturally.
You can implement forloop|continue and forloop|break with custom filters.
http://djangosnippets.org/snippets/2093/
For-loops in Django templates are different from plain Python for-loops, so continue and break will not work in them. See for yourself in the Django docs, there are no break or continue template tags. Given the overall position of Keep-It-Simple-Stupid in Django template syntax, you will probably have to find another way to accomplish what you need.
For most of cases there is no need for custom templatetags, it's easy:
continue:
{% for each in iterable %}
{% if conditions_for_continue %}
<!-- continue -->
{% else %}
... code ..
{% endif %}
{% endfor %}
break use the same idea, but with the wider scope:
{% set stop_loop="" %}
{% for each in iterable %}
{% if stop_loop %}{% else %}
... code ..
under some condition {% set stop_loop="true" %}
... code ..
{% endif %}
{% endfor %}
if you accept iterating more than needed.
If you want a continue/break after certain conditions, I use the following Simple Tag as follows with "Vanilla" Django 3.2.5:
#register.simple_tag
def define(val=None):
return val
Then you can use it as any variable in the template
{% define True as continue %}
{% for u in queryset %}
{% if continue %}
{% if u.status.description == 'Passed' %}
<td>Passed</td>
{% define False as continue %}
{% endif %}
{% endif %}
{% endfor %}
Extremely useful for any type of variable you want to re-use on template without using with statements.
I am looking for way to clean up a template in django. A simple solution would be to break this up into multiple templates, but we do not want to do that.
We basically have the following
{%if data.some_state %}
Display some markup
{% else %}
{%if data.some_state_2 %}
State 2 different html view
{% else %}
{%if data.process_data %}
Display some list of data
{% else %}
No Data to display!
{% endif %} <!-- if data.process_data-->
{% endif %} <!-- if data.some_state_2 -->
{% endif %} <!-- if data.some_state -->
So that is extremely confusing and hard to read. If I could do this in a "function" i would use if/else if or returns.
Is there a way in template language to do something like (stop_processing_template would tell the template we are done... ):
{%if data.some_state %}
Display some markup
{% endif %}
{% django_stop_processing_template %}
{%if data.some_state_2 %}
State 2 different view
{% endif %}
{% django_stop_processing_template %}
{%if data.process_data %}
Display some list of data
{% endif %}
{% django_stop_processing_template %}
No data provided !
I am not sure what your stop processing template logic would do; but a cleaner way to do your logic would be to write a custom tag that takes your arguments and then returns only the HTML relevant to your variables. This way you remove the if/else loops and instead replace all that with a simple {% do_stuff %} tag.
Edit
This is a very simple implementation to give you some idea on how the logic would go.
First, you create templates for each variation and store them somewhere django can find them.
Then, a simple tag that renders the exact template you want (this is non tested, psuedo):
from django import template
from django.db.models import get_model
register = template.Library()
class ProcessData(template.Node):
def __init__(self, var_name):
self.obj = get_model(*var_name.split('.'))
def render(self, context):
if self.obj.some_state:
t = template.loader.get_template('some_markup_template.html')
result = 'something'
else:
if self.obj.some_state_2:
t = template.loader.get_template('some_different_html_view.html')
result = 'something'
else:
if self.obj.process_data:
t = template.loader.get_template('some_list_data.html')
result = 'something'
else:
t = template.loader.get_template('no_data.html')
result = 'something'
return t.render(Context({'result': result}, autoescape=context.autoescape))
#register.tag
def process_data(parser, token):
try:
tag_name, arg = token.contents.split(None, 1)
except ValueError:
raise template.TemplateSyntaxError("%r tag requires arguments" % token.contents.split()[0])
return ProcessData(arg)
Finally, in your template:
{% load my_tags %}
{% process_data data.mymodel %}
You could use jinaj2 for templating that view (or the whole project), it supports if/elif/else branching:
{% if data.some_state %}
Display some markup
{% elif data.some_state_2 %}
State 2 different view
{% elif data.process_data %}
Display some list of data
{% endif %}
There are a couple different packages which it easy use jinja2 in a django project, I've used both coffin and djinja for this.
Though I think #burhan's approach is better, you could also do what you want to do by using a custom tag that sets a context variable to a boolean and than outermost else part could also be converted into a if tag
#Set a context variable nodata to True
{% setnodata True %}
{%if data.some_state %}
Display some markup
#Set context variable nodata to False
{% setnodata False %}
{% endif %}
{%if data.some_state_2 %}
State 2 different view
#Set context variable nodata to False
{% setnodata False %}
{% endif %}
{%if data.process_data %}
Display some list of data
#Set context variable nodata to False
{% setnodata False %}
{% endif %}
{% if nodata %}
No data provided !
{ % endif %}
The setnodata custom tag simply sets the context variable nodata to True or False depending upon the argument.
today I meet the same question.
And I find this tag {% verbatim %} {% endverbatim %} .This works in Django1.5+
An example:
{% verbatim %}
<div class="entry">
<h1>{{ title }}</h1>
<div class="body">
{{ body }}
</div>
</div>
{% endverbatim %}
You can also look below for more details:
https://groups.google.com/forum/#!topic/django-users/-_wBLDuzaNs
Handlebars.js in Django templates