I have a problem, thats probably very simple,
I have a list of strings, that I pass as variable to a template called s_name
If I print the list elements on the view side I see them ok, but on the html they got rendered this way
['PB14'], ['HHZ']
In order to rescue each element, I'm doing slicing on the list,
{% with y=forloop.counter0|stringformat:"s" %}
{% with z=forloop.counter0|add:1|stringformat:"s" %}
{% with mySlice=""|add:y|add:":"|add:z %}
{{ s_name|slice:mySlice }}
{% endwith %}
{% endwith %}
{% endwith %}
Thanks
The problem was that the output of slice was another list, (thanks #SimeonVisser)
So the solution was to convert to a string again using {{ value|join:"" }}
Related
It is able to write {{ myval.add:5 }}, {{ myval|add:value }} and even {{ myval|add:-5 }}.
However, I can't find out what I should type to add value * -1 like {{ myval|add:-value }}. This doesn't work, sadly.
You need to use double quotes:
{{ myval|add:"-5" }}
This subtracts five from myval.
The built-in Django template tags/filters aren't all-encompassing, but it's super easy to write your own custom template tags: https://docs.djangoproject.com/en/dev/howto/custom-template-tags/
You could make your own subtract template tag pretty easily:
#register.filter
def subtract(value, arg):
return value - arg
Use django-mathfilters from PyPI: https://pypi.python.org/pypi/django-mathfilters
To install :
$ pip install django-mathfilters
Then add mathfilters in your INSTALLED_APPS.
In template:
{% load mathfilters %}
<ul>
<li>8 + 3 = {{ 8|add:3 }}</li>
<li>13 - 17 = {{ 13|sub:17 }}</li>
{% with answer=42 %}
<li>42 * 0.5 = {{ answer|mul:0.5 }}</li>
{% endwith %}
{% with numerator=12 denominator=3 %}
<li>12 / 3 = {{ numerator|div:denominator }}</li>
{% endwith %}
<li>|-13| = {{ -13|abs }}</li>
</ul>
I recently started working with Django and stumbled upon this one as well: I needed a very simple template loop that stops printing after n times and shows a "more" link to toggle the rest of the items.
With great interest I read the struggle of people trying to understand why this is not being added to the Django default filters (since before 2013). I didn't feel like creating a custom template tag and I kind of found a way to subtract 2 variables using strings and add in combination with with and stringformat
Let's say I have a list of items where I want to print the first 2 and hide the rest, showing how many hidden items are there, eg.
John, Anna and 5 others like this (when given a list of 7 items)
As long as the number of visible items is harcoded in the template (eg. 2), it's possible to add the negative 2 |add:"-2", but I wanted the number of visible items to be a variable as well. The Math-filter library as suggested above doesn't seem up to date (I haven't tested it with Django 2.x).
The trick seems to be to use the add helper to concat the strings "-" with the integer as string, so it can be coerced back to a negative integer in a any consecutive calls to the add helper. This doesn't work however if the value is not a string, so that's where the stringformat helper comes in.
With string value
template posts.html (note how visible is explicitely passed as string - alternative below)
{% for post in posts %}
<h4>{{ post.title }}</h4>
...
{% include 'show_likes.html' with likes=post.likes visible="3" %}
{% endfor %}
template show_likes.html (note the add:0 to make the boolean operator work)
{% with show=visible|default:"2" %}
{% for like in likes %}
{% if forloop.counter <= show|add:0 %}
{% if not forloop.first %},{% endif %}
{{ like.username }}
{% endif %}
{% endfor %}
{% if likes|length > show|add:0 %}
{% with rest="-"|add:show %}
and {{ likes|length|add:rest }} more
{% endwith %}
{% endif %}
like this
{% endwith %}
Alternative with integer
You could just convert your integer to a string in the calling template using |stringformat:"d"
If however the number of visible items you want to show is an integer, you'll have to add a call to stringformat:"d" to have it converted to string
template posts.html
{% for post in posts %}
<h4>{{ post.title }}</h4>
...
{% include 'show_likes.html' with likes=post.likes visible=3 %}
{% endfor %}
template show_likes.html
{% with show=visible|default:2 %}
{% with show_str=show|stringformat:"d" %}
{% for like in likes %}
{% if forloop.counter <= show %}
{% if not forloop.first %},{% endif %}
{{ like.username }}
{% endif %}
{% endfor %}
{% if likes|length > show|add:0 %}
{% with rest="-"|add:show_str %}
and {{ likes|length|add:rest }} more
{% endwith %}
{% endif %}
{% endwith %}
{% endwith %}
Since I'm a very beginner with Django and Python, I'm pretty sure this approach is far worse than actually creating a custom helper! So I'm not suggesting anyone should be using this. This was just my attempt on trying to solve this with the available template helpers and without any custom stuff.
Hope this helps
Lo primero es multiplicar por -1 para convertirlo en una valor negativo y guardarlo en una variable y posterior a usar la suma
The first thing is to multiply by -1 to turn it into a negative value
and save it in a variable and then use the add
{% widthratio val2 1 -1 as result %}
{{result|add:val1}}
After search I found that I can make {% with var=value %} with filters to make the arithmetic operations "with other variables or not"
For example: I have x = 5 and y = 3 and need to add the y's value to x value, all what I need is these steps:
1- Create variable x : {% with x=5 %}
2- Create variable y : {% with y=3 %}
3- In my HTML tags, say <h1>, write that : <h1>{{ x|add:y }}</h1>
4- Close the y's with : {% endwith %}
5- Close the x's with : {% endwith %}
Hope it works with you, it worked with me.
{% with i=3 %}
{% with x=1 %}
<h1>{{i|add:x}}</h1> <!-- result is 4 -->
{% endwith %}
{% endwith %}
I am newbie in django. How can I concat string in a for loop in django template
{% for lead in project.leaders %}
{% if forloop.counter == 1 %}
{% lead_member = lead.0 %}
{% else %}
{% lead_member = ','.lead.0 %}
{% endif %}
{{ lead_member }}
{% endfor %}
Finally my lead_member should be test1,test2,test3....
what is happening now (my current code)
{% for lead in project.leaders %}
{{ lead.0}}
{% endfor %}
and the output is test1test2test3.... but i want to make same as test1,test2,test3....
Try this. it works
{% for lead in project.leaders %}
{{ lead.0 }}{% if not forloop.last %}, {% endif %}
{% endfor %}
There's no need to assign anything, nor do you need that type of complexity by using assignment tags. To keep your templating stupid-simple, you could always do this in your view, or even at the model level:
# don't step on the `join` built-in
from django.template.defaultfilters import join as join_filter
class Project(models.Model):
#property
def leaders(self):
return join_filter(self.objects.values_list('some_field', flat=True), ', ')
Then all you have to do in the template is:
{{ project.leaders }}
It's hard to understand your question, but I hope i did it. There is a number of related questions such as String-concatination,
How to concatenate in django
It's possible to create first string, concatinate it with comma and new string for every iteration. You are also able to make smth like ','.join(list_of_strings) on your server side before rendering. You can also join your list in templating by {{ list|join:", " }}.
For example, there is an object in a nested loop:
{% for fieldset in inline_admin_form %}
{% for line in fieldset %}
{% for field in line %}
{% if field.is_hidden %} {{ field.field }} {% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endif %}
Now I want to check the class name and some information about field.field, so I use field.field.__repr__() to replace field.field.
However, the django template complains about it after the change:
Variables and attributes may not begin with underscores: 'field.field.__repr__'
Does anyone have idea about this? And is there any better way to debug for a variable in django template? (I tried {% debug %} but found it awful when I want to check a variable in a nested loop..)
{{ value|stringformat:'r' }}
uses the string % operator style formatting with the r format which uses repr()
You could easily write a template filter which allows you to do {{ var|asrepr }}. See the documentation, but it'll look something like this:
#register.filter
def asrepr(value):
return repr(value)
I am already trying to concatenate like this:
{% for choice in choice_dict %}
{% if choice =='2' %}
{% with "mod"|add:forloop.counter|add:".html" as template %}
{% include template %}
{% endwith %}
{% endif %}
{% endfor %}
but for some reason I am only getting "mod.html" and not the forloop.counter number. Does anyone have any idea what is going on and what I can do to fix this issue? Thanks alot!
Your problem is that the forloop.counter is an integer and you are using the add template filter which will behave properly if you pass it all strings or all integers, but not a mix.
One way to work around this is:
{% for x in some_list %}
{% with y=forloop.counter|stringformat:"s" %}
{% with template="mod"|add:y|add:".html" %}
<p>{{ template }}</p>
{% endwith %}
{% endwith %}
{% endfor %}
which results in:
<p>mod1.html</p>
<p>mod2.html</p>
<p>mod3.html</p>
<p>mod4.html</p>
<p>mod5.html</p>
<p>mod6.html</p>
...
The second with tag is required because stringformat tag is implemented with an automatically prepended %. To get around this you can create a custom filter. I use something similar to this:
http://djangosnippets.org/snippets/393/
save the snipped as some_app/templatetags/some_name.py
from django import template
register = template.Library()
def format(value, arg):
"""
Alters default filter "stringformat" to not add the % at the front,
so the variable can be placed anywhere in the string.
"""
try:
if value:
return (unicode(arg)) % value
else:
return u''
except (ValueError, TypeError):
return u''
register.filter('format', format)
in template:
{% load some_name.py %}
{% for x in some_list %}
{% with template=forloop.counter|format:"mod%s.html" %}
<p>{{ template }}</p>
{% endwith %}
{% endfor %}
You probably don't want to do this in your templates, this seems more like a views job: (use of if within a for loop).
chosen_templates=[]
for choice in choice_dict:
if choice =='2':
{% with "mod"|add:forloop.counter|add:".html" as template %}
template_name = "mod%i.html" %index
chosen_templates.append(template_name)
Then pass chosen_templates to your template where you will have only
{% for template in chosen_templates %}
{% load template %}
{% endfor %}
Also, I don't quite understand why you are using a dict to select the template with a number that is not in the dictionnary. for key,value in dict.items() may be what you are looking for.
Try without using the block "with"
{% for choice in choice_dict %}
{% if choice =='2' %}
{% include "mod"|add:forloop.counter|add:".html" %}
{% endif %}
{% endfor %}
I'm new to django and can't find a way to get this to work in django templates. The idea is to check if previous items first letter is equal with current ones, like so:
{% for item in items %}
{% ifequal item.name[0] previous_item.name[0] %}
{{ item.name[0] }}
{% endifequal %}
{{ item.name }}<br />
{% endforeach %}
Maybe i'm trying to do this in wrong way and somebody can point me in right direction.
Use the {% ifchanged %} tag.
{% for item in items %}
{% ifchanged item.name.0 %}
{{ item.name.0 }}
{% endifchanged %}
{% endfor %}
Also remember you have to always use dot syntax - brackets are not valid template syntax.