how to use objects in django template - django

I have such object:
data[ 'aaa' ] = ['1', 'something1']
data[ 'bbb' ] = ['2', 'something2']
And want to display it (using loop ) in template :
{% for row in data %}
<span>{{ row }}</span>>
{% for d in data.row %}
{{ d.0 }} || {{ d.1 }}
{% endfor %}
{% endfor %}
But i see only values within the span tag ( even though array is not empty )
Can you tell me what I am doing wrong ?
Thanks in advance,

The way you're trying to iterate over each row doesn't make sense - either you iterate, or you fetch by index, but doing both will not work. Try this instead:
{% for row in data %}
{{ d.0 }} || {{ d.1 }}
{% endfor %}

Related

Apply if-else statement on a dictionary using django-templates

In a django - webapp I am classifying between two classes of images i.e. Ants and Bees
I have returned the dictionary to the templates(index.html)
context={
'ant':("%.2f" % predictions[0]),
'bee': ("%.2f" % predictions[1]),
}
when applying this
{% for key , value in pred.items %}
<p>{{key}}: {{value}}%</p>
{% endfor %}
i got this which is pretty much what i wanted to display now i want to display the one with greater probability how do i do it ?
I cannot access elements of the dictionary inside if else statement , though i tried doing this
{% for key, value in pred.items %}
{% if value.0 > value.1 %}
<p>Result : {{value.0}}</p>
{% elif value.0 < value.1 %}
<p>Result: {{key}}</p>
{% endif %}
{% endfor %}
Since your data structure does not look very dynamic and flexible, you could do it the following static way:
Result:
{% if pred.ant > pred.bee %}
Ant: {{ pred.ant }}
{% elif pred.ant < pred.bee %}
Bee: {{ pred.bee }}
{% else %}
Ant: {{ pred.ant }}
Bee: {{ pred.bee }}
{% endif %}

How to store and access values outside loop in jinja

I have seen few Questions asking same , but I could not figure out how to
I have a for loop as:
{% for brands in data %}
{{ brands['brand'] }} // 'test1','test2'.....
{% endfor %}
I am trying to access the brands['brand'] values outside of loop , I am doing as:
{% set newlist = [] %}
{% for brands in data %}
{% set newlist = newlist.append(brands['brand']) %}
{{ brands['brand'] }} // 'test1','test2'.....
{% endfor %}
now when I access newlist as {{ newlist }} after loop it gives me result
But, May I know how can i access the newlist above declaration ? (sorry if this doesn't make any sense)
Any help is appreciated ...TIA
Please change this piece of code :
{% set newlist = newlist.append(brands['brand']) %}
to this :
{% set newlist = newlist.append( {{ brands['brand'] }} ) %}

Accessing multiple dictionaries in list using for loop in Django Templates

I have been working on a project and it requires me to access dictionaries that are in a list. I am using Django 2.0. This is my code here.
{% if dictdata %}
{% for x in range %}
{{ "in loop" }}
{{ dictdata.x.name }}
{% endfor %}
{{ dictdata.0.name }}
{{ dictdata.1.name }}
{% endif %}
The two statement after the for loop are working fine. But the one in the loop is not returning anything but printing the message 'in loop'. dictdatais a list containing dictionaries.
It is not clear what the value of your range varable is. So assuming dictdata is close to the following:
dictdata = [
{'name': 'Bob'},
{'name': 'John'}
]
You can loop over them in your template as follows:
{% for d in dictdata %}
{{ d.name }}
{% endfor %}
Documentation about looping in a template can be found here.

Template adding value in variable declared using with

Can some one please explain me why the below code is not adding the value in current_count variable. Also I am using django version 1.3. The below code gives following output.
0
"image"
10
"image"
10
"image"
.
.
.
The "image" means actual image is shown.
What I want is "only show 4 images".
{% with current_count=0 %}
{% for row in people|slice:":4" %}
{% if row %}
{% for event in row %}
{% if current_count < 4 %}
{{current_count}}
<div class="latest-photos-image-box">
<img src="{{ event.mainthumb.url }}" alt="{{ event.title }}" />
</div>
{% endif %}
{{ current_count|add:"1" }}
{% endfor %}
{% endif %}
{% endfor %}
{% endwith %}
The problem here is that {{ current_count|add:"1" }} does the addition but doesn't store anything. Please use the loop counters forloop.counter instead.
However, if you need a counter that works regardless of nesting level; here is a recipe (haven't tested but should work):
>>> def monotonic():
... count = 0
... while True:
... yield count
... count += 1
...
>>> counter = monotonic()
>>> # pass it to you request context dictionary
and use {{ counter.next }} each time you need it.
Please also check out this question: Flatten list of lists , you may want to flatten your list of rows of people to a more simple list of people that you can then slice.
{% for event in row|slice:":4" %}
And get rid of the rest.

Numeric for loop in Django templates

How do I write a numeric for loop in a Django template? I mean something like
for i = 1 to n
I've used a simple technique that works nicely for small cases with no special tags and no additional context. Sometimes this comes in handy
{% for i in '0123456789'|make_list %}
{{ forloop.counter }}
{% endfor %}
{% with ''|center:n as range %}
{% for _ in range %}
{{ forloop.counter }}
{% endfor %}
{% endwith %}
Unfortunately, that's not supported in the Django template language. There are a couple of suggestions, but they seem a little complex. I would just put a variable in the context:
...
render_to_response('foo.html', {..., 'range': range(10), ...}, ...)
...
and in the template:
{% for i in range %}
...
{% endfor %}
My take on this issue, i think is the most pythonic. Create a my_filters.py in your apps templatetags directory.
#register.filter(name='times')
def times(number):
return range(number)
Usage in your template:
{% load my_filters %}
{% for i in 15|times %}
<li>Item</li>
{% endfor %}
You can pass a binding of
{'n' : range(n) }
to the template, then do
{% for i in n %}
...
{% endfor %}
Note that you'll get 0-based behavior (0, 1, ... n-1).
(Updated for Python3 compatibility)
Maybe like this?
{% for i in "x"|rjust:"100" %}
...
{% endfor %}
I'm just taking the popular answer a bit further and making it more robust. This lets you specify any start point, so 0 or 1 for example. It also uses python's range feature where the end is one less so it can be used directly with list lengths for example.
#register.filter(name='range')
def filter_range(start, end):
return range(start, end)
Then in your template just include the above template tag file and use the following:
{% load myapp_filters %}
{% for c in 1|range:6 %}
{{ c }}
{% endfor %}
Now you can do 1-6 instead of just 0-6 or hard coding it. Adding a step would require a template tag, this should cover more uses cases so it's a step forward.
You can pass :
{ 'n' : range(n) }
To use template :
{% for i in n %}
...
{% endfor %}
I tried very hard on this question, and I find the best answer here:
(from how to loop 7 times in the django templates)
You can even access the idx!
views.py:
context['loop_times'] = range(1, 8)
html:
{% for i in loop_times %}
<option value={{ i }}>{{ i }}</option>
{% endfor %}
You don't pass n itself, but rather range(n) [the list of integers from 0 to n-1 included], from your view to your template, and in the latter you do {% for i in therange %} (if you absolutely insist on 1-based rather than the normal 0-based index you can use forloop.counter in the loop's body;-).
Just incase anyone else comes across this question… I've created a template tag which lets you create a range(...): http://www.djangosnippets.org/snippets/1926/
Accepts the same arguments as the 'range' builtin and creates a list containing
the result of 'range'.
Syntax:
{% mkrange [start,] stop[, step] as context_name %}
For example:
{% mkrange 5 10 2 as some_range %}
{% for i in some_range %}
{{ i }}: Something I want to repeat\n
{% endfor %}
Produces:
5: Something I want to repeat
7: Something I want to repeat
9: Something I want to repeat
You should use "slice" in template, a example like this:
in views.py
contexts = {
'ALL_STORES': Store.objects.all(),
}
return render_to_response('store_list.html', contexts, RequestContext(request, processors=[custom_processor]))
in store_list.html:
<ul>
{% for store in ALL_STORES|slice:":10" %}
<li class="store_item">{{ store.name }}</li>
{% endfor %}
</ul>
This method supports all the functionality of the standard range([start,] stop[, step]) function
<app>/templatetags/range.py
from django import template
register = template.Library()
#register.filter(name='range')
def _range(_min, args=None):
_max, _step = None, None
if args:
if not isinstance(args, int):
_max, _step = map(int, args.split(','))
else:
_max = args
args = filter(None, (_min, _max, _step))
return range(*args)
Usage:
{% load range %}
<p>stop 5
{% for value in 5|range %}
{{ value }}
{% endfor %}
</p>
<p>start 5 stop 10
{% for value in 5|range:10 %}
{{ value }}
{% endfor %}
</p>
<p>start 5 stop 10 step 2
{% for value in 5|range:"10,2" %}
{{ value }}
{% endfor %}
</p>
Output
<p>stop 5
0 1 2 3 4
</p>
<p>start 5 stop 10
5 6 7 8 9
</p>
<p>start 5 stop 10 step 2
5 7 9
</p>
This essentially requires a range function. A Django feature ticket was raised (https://code.djangoproject.com/ticket/13088) for this but closed as "won't fix" with the following comment.
My impression of this idea is that it is trying to lead to programming in the template. If you have a list of options that need to be rendered, they should be computed in the view, not in the template. If that's as simple as a range of values, then so be it.
They have a good point - Templates are supposed to be very simple representations of the view. You should create the limited required data in the view and pass to the template in the context.
{% for _ in ''|center:13 %}
{{ forloop.counter }}
{% endfor %}
If the number is coming from a model, I found this to be a nice patch to the model:
def iterableQuantity(self):
return range(self.quantity)
You can use:
{% with ''|center: i as range %}
For those who are looking to simple answer, just needing to display an amount of values, let say 3 from 100 posts for example just add {% for post in posts|slice:"3" %} and loop it normally and only 3 posts will be added.
This shows 1 to 20 numbers:
{% for i in "x"|rjust:"20"|make_list %}
{{ forloop.counter }}
{% endfor %}
also this can help you:
(count_all_slider_objects come from views)
{% for i in "x"|rjust:count_all_slider_objects %}
{{ forloop.counter }}
{% endfor %}
or
{% with counter=count_all_slider_objects %}
{% if list_all_slider_objects %}
{% for slide in list_all_slider_objects %}
{{forloop.counter|add:"-1"}}
{% endfor%}
{% endif %}
{% endwith %}
You can pass range(n) instead of n in the context in views.py. This will give you an iterable list.
context['range']= range(n)
Then you can iterate in your template this way:
{% for i in range %}
<!-- your code -->
{% endfor %}
{% for i in range(10) %}
{{ i }}
{% endfor %}