Separator Between Multiple Variables in Django Template (DTL) - django

Given three or more variables in my DTL template what is the most convenient way to assure that an interpunct is always between two variables?
<div>{{ person.name }} · {{ person.phone }} · {{ person.city }}</div>
Expected:
<div>John · 1234567 · New York</div>
<!-- {{ person.city }} is null or empty-->
<div>John · 1234567</div>
Is there an easy way to solve this with built-in functionality? I try to avoid writing custom Django filters/template tags.

You can't do this easily in Django template language. Either pass a list of non-empty values from your view, e.g. ["John", "1234567"], or write a custom tag or filter so that you can do something like {% interpunct person.name person.phone person.city %} or {{ person|display_person }}.

You can (ab)use the cycle tag for this purpose. Place it in front of each list item, then use it to emit nothing on first pass, then the separator thereafter. Use in a for loop is straightforward. Use outside needs this pattern:
{% cycle '' '|' '|' '|' as itemsep silent %}
{% if foo %}
{{ itemsep }}{% cycle itemsep %}
Foo!
{% endif %}
{% if bar %}
{{ itemsep }}{% cycle itemsep %}
Bar!
{% endif %}
{% if foobar %}
{{ itemsep }}{% cycle itemsep %}
FooBar!
{% endif %}
Or, miss the silent complexity by just using an extra ''
{% cycle '' '' '|' '|' '|' as itemsep %}
{% if foo %}
{% cycle itemsep %}
Foo!
{% endif %}
...

Related

Remove/Strip extra space from the output of for...loop in Django template

In my template I need to print some items and add "," after each one, unless it is the last item.
So here is my code:
<li>
<strong>Category</strong>:
{% spaceless %}
{% for t in project.technology.all %}
{{ t.title }}
{% if not forloop.last %},{% endif %}
{% endfor %}
{% endspaceless %}
</li>
While it works, it adds an extra whitespace between each item and ",", so what I see is like this:
Tech1 , Tech2 , Tech3 while it should be Tech1, Tech2, Tech3
Even spaceless template tag is not working.
As the documentation of {% spaceless %} [Django-doc] says:
Only space between tags is removed – not space between tags and text.
It is thus only the space between tags, not between tags and text, text and text, etc.
You can render this with:
<li>
<strong>Category</strong>:
{% for t in project.technology.all %}
{{ t.title }}{% if not forloop.last %}, {% endif %}
{% endfor %}
</li>
we thus will not render a space between {{ t.title }} and the comma, since these are all template tags that do not output anything.

How to display text if the field is empty?

How to display a text if the field is empty ?
I tried the following code but it does not work :
{% if content.field_description is not empty %}
{{ content.field_description }}
{% else %}
test
{% endif %}
If you have Twig Tweak installed, you can do the following:
{% if content['field_description'] | field_value != '' %}
{{ content['field_description'].value | striptags }}
{% else %}
<p class="des-empty">test</p>
{% endif %}
When field is empty it is not coming with content variable
so you can simply check by isset
{% if content.field_description %}
{{ content.field_description }}
{% else %}
<p class="des-empty">test</p>
{% endif %}
The below worked for me:
{% if content['field_description'] IS NOT EMPTY %}
{{ content['field_description'].value | striptags }}
{% else %}
<p class="des-empty">test</p>
{% endif %}
Please note that it may vary based on the content type and fields you are dealing with.

Django list in template without trailing comma in a nested for loop

I am trying to create a list of items in a Django template that are separated by commas, but with no comma after the last item. The list of items comes through a for loop within a for loop. I tried to do something like this.
{% for thing in things %}
{% spaceless %}
{% for o in thing.otherthing_set.all %}
<span>{{ o.name }}: </span>
{% if o.attribute == 'this' %}
<span>{{ o.otherattribute}}</span>
{% if not forloop.last %}
<span>, </span>
{% endif %}
{% endif %}
{% endfor %}
{% endspaceless %}
<br>
{% endfor %}
But sometimes there is an extra comma because sometimes for the last item cycled through o.attribute == 'this' isn't always true.
What I would like to do is somehow have
{% for o in thing.otherthing_set.all %}
be filtered for just for o.attribute == 'this' before even going through the for loop, but it doesn't seem that this is possible.
Any suggestions?

Last element in django template list variable

I would like to know how to filter out the last element of a list variable from the context object.
{% for d in data %}
{{ d }},
{% endfor %}
I don't want to have the , after the last element. Thank you.
NOTE: This is just a hypothetical example. I know we can use the join filter to achieve the same thing here
Do you mean -
{% for d in data %}
{% if forloop.last %}
{{ d }}
{% else %}
{{ d }},
{% endif %}
{% endfor %}
have a look at the django docs on template for loops
Use {{ data|join:", " }}, it does exactly what you need.
https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#join
Or you can try this as well -
{% for d in data %}
{{ d }} {% if not forloop.last %},{% endif %}
{% endfor %}
have a look at the docs on template for loops

How to escape liquid template tags?

This sounds very easy, however I couldn't find it anywhere in the docs. How can I write {% this %} in a liquid template, without it being processed by the engine?
it is possible to disable liquid processing engine using the raw tag:
{% raw %}
{% this %}
{% endraw %}
will display
{% this %}
For future searchers, there is a way to escape without plugins, use the code below:
{{ "{% this " }}%}
and for tags, to escape {{ this }} use:
{{ "{{ this " }}}}
There is also a jekyll plugin for this which makes it a whole lot easier: https://gist.github.com/1020852
Raw tag for jekyll. Keeps liquid from parsing text betweeen {% raw %}
and {% endraw %}
Reference
BTW:
If you want to display {{ "{% this " }}%}in Jekyll, you can code like this:
{{ "{{ " }}"{{ "{% this" }} " }}{{ "}}%}
To escape {{ "{{ this " }}}}use:
{{ "{{ " }}"{{ "{{ this" }} " }}{{ "}}}}
You can escape liquid tags in Jekyll posts using {% raw %} {% endraw %} i.e
{% raw %}
{% for post in site.posts %}
{{ post.content }}
{% endfor %}
{% endraw %}
will produce
{% for post in site.posts %}
{{ post.content }}
{% endfor %}
There is another option: to use HTML special characters codes for replacing the curly braces with its matching codes:
replace each { with {
replace each } with }
For more details about this solution see:
http://www.tikalk.com/devops/curly_brances_workaround/
I found a omnipotent way to display any text with curly braces. You can assign plain text to a variable, and display it.
{% assign var = "{{ sth }}" %}
{{ var }}
As mentioned here also, plain {% raw %} and {% endraw %} are only the second best solution since those are shown if you look up the Markdown on normal github.com.
The best way is to put {% raw %} and {% endraw %} in HTML comments:
<!-- {% raw %} -->
something with curlky brackets like { this } and { that }
<!-- {% endraw %} -->
Due to the HTML comments it is seen by Github as a comment. In Github pages the raw tags will prevent the parsing of the curly brackets in between the tags.
I tried {% raw %} something {% endraw %} ,
and {{ "{% this " }}%}. But they both don't work.
finally, my working answer is
{{ "{%" xxx }} something }}.
My code:
{{ "{%" }} extends 'xadmin/base_site.html' %}
{{ "{%" }} block nav_form %}
<h3>{{ "{{" }} title }}</h3>
{{ "{%" }} for i in context1 %}
<p>{{ "{{" }} i }}</p>
{{ "{%" }} endfor %}
{{ "{%" }} endblock %}
The result:
{% extends 'xadmin/base_site.html' %}
{% block nav_form %}
<h3>{{ title }}</h3>
{% for i in context1 %}
<p>{{ i }}</p>
{% endfor %}
{% endblock %}
Allows output of Liquid code on a page without being parsed.
{% raw %}{{ 5 | plus: 6 }}{% endraw %} equals 11.
{{ 5 | plus: 6 }} equals 11.
For more details about this solution see: https://www.shoplazza.dev/docs/theme-tags