Make a django template object iterable - python

I have a dictionary with a number of characteristics:
sort_options = SortedDict([
("importance" , ("Importance" , "warning-sign" , "importance")),
("effort" , ("Effort" , "wrench" , "effort")),
("time_estimate" , ("Time Estimate" , "time" , "time_estimate")),
])
I also have a list of actions as a query result. Each action has these attributes; In my template, I can call {{ action.effort }} or {{ action.time_estimate }} and get a result.
I'm iterating through my sort_options to populate twitter bootstrap icons:
{% for key, icon in sort_options.items %}
<i class="icon-{{ icon.1 }}"></i>
{% endfor %}
But I also want to display the action value for each of these attributed. Essentially, something like:
{% for key, icon in sort_options.items %}
<i class="icon-{{ icon.1 }}"></i>
{{ action.key }}
{% endfor %}
Where key would resolve to "importance" or "effort". I know this doesn't work. So I was trying to leverage the solution presented in this question.
The solution proposed a template filter:
def hash(h,key):
if key in h:
return h[key]
else:
return None
register.filter(hash)
{{ user|hash:item }}
Where the question used a dictionary that looked like so:
{'item1': 3, 'name': 'username', 'item2': 4}
I tried the following:
{% for key, icon in sort_options.items %}
<i class="icon-{{ icon.1 }}"></i>
{{ action|hash:key }}
{% endfor %}
But got an error:
Caught TypeError while rendering: argument of type 'Action' is not iterable
I believe this is because the template filter is getting just one attribute of the object (likely the name) as opposed to the whole dictionary:
[<Action: Action_one>, <Action: Task_two>...]
Is there a way to force the template to pass the full object to the template tag?

I think I finally get it. You want the equivalent of
getattr(action, key)
in your template. This answer describes the getattribute templatetag you'd need to do so.

Related

How to access the dictionary keys and values in django templates

I have created a dictionary of message senders which is updating dynamically. If I print the dictionary keys in the python console window, I am getting the expected output but when I try to access the values in the Django template, I am getting nothing here is my python code;
views.py
def home(request):
senders = {}
chatting =Message.objects.filter(seen=False)
for msg in chatting:
user = User.objects.get(id=msg.sender.id)
if user != request.user and user not in senders.values():
senders.update({user.id : user})
return render(request, 'home.html', senders)
template Home.html
<div>
{% for key, val in senders %}
<div>
{{val}}
</div>
{% endfor %}
</div>
first of all,
are you sure you really need a dict here? usually Django has a list of dicts. So, you loop just list, like here: https://github.com/ansys/aedt-testing/blob/cefebb91675dd54391d6324cd78e7bc97d9a8f6b/aedttest/static/templates/project-report.html#L220
however,
answer to a direct question:
{% for key, value in data.items %}
{{ key }}: {{ value }}
{% endfor %}
https://docs.djangoproject.com/en/dev/ref/templates/builtins/#for
use below instruction in template of django :
{{ key }}: {{ value }}

Looping through nested dictionary in Django template

My context dictionary for my Django template is something like the following:
{'key1':'1',
'key2':'2',
'key3':'3',
'key4':{'key5':{'key6':'6', 'key7':'7', 'key8':'8'}}}
I would like to iterate through the dictionary and print something like:
some label = 6
some label = 7
some label = 8
How can I achieve this in my Django template?
What's wrong with this ?
<ul>
{% for key, value in key4.key5.items %}
<li>{{ key }} : {{ value }}</li>
{% endfor %}
</ul>
NB: you didn't ask for looping over all keys in the context, just about accessing key4['key5'] content. if this wasn't wath you were asking for pleasit eadit your question to make it clearer ;-)
I am guessing you want to use a for loop in the django template to do this you must first pass the dictionary to the template in the views file like so make sure you add square brackets around the dictionary like this:
data = [{'key1':'1',
'key2':'2',
'key3':'3',
'key4':{'key5':{'key6':'6', 'key7':'7', 'key8':'8'}}
}]
return render(request,'name of template',{'data':data})
then in the html template:
{% for i in data%}
<p>{{i.key1}}</p>
<p>{{i.key2}}</p>
<p>{{i.key3}}</p>
<p>{{i.key4.key5.key6}}</p>
{% endfor %}
Now when you do the for loop you can access all the iteams in key4 like i have above when I put {{i.key4.key5.key6}}
Here is the docs for the for loop in django templates https://docs.djangoproject.com/en/3.0/ref/templates/builtins/
I am assuming thats what you want to do.
This has worked for me:
{% for key, value in context.items %}
{% ifequal key "key4" %}
{% for k, v in value.items %}
some label = {{ v.key6 }}
some label = {{ v.key7 }}
some label = {{ v.key8 }}
{% endfor %}
{% endif %}
{% endfor %}
If you want to print only what you have mentioned in question then it is possible but if we don't know the exact structure of dictionary then it is possible in django views not in django template.
You can't print value which is also a dictionary one by one in django template,
But you can do this in django view.
Check this post click here and do some changes in views.

adding an integer postfix or prefix to an html attribute with flask-wtforms

I have the following thing in a jinja2 for loop:
{{ meal[item]['open-modal'].submit(**{ 'class':'btn btn-primary',
'data-toggle':'modal',
'data-target':'#myModal' }) }}
I need to have an index on the data-target like:
{{ meal[item]['open-modal'].submit(**{ 'class':'btn btn-primary',
'data-toggle':'modal',
'data-target':'#myModal-item' }) }}
item is the index needed in this case. Is there a way to escape item out of this "ad-hoc dictionary"? So that it takes on the same values as in meal[item]?
I need the 'data-target' attribute to render as '#myModal-0', '#myModal-1', etc.. As it stands each 'data-target' attribute gets set as '#myModal-item' for each item in the loop. In other words it sets item in the second line of code as a string.
In case it is ever helpful for someone, what wound up solving my problem was:
<form method="POST">
{{ meal[item]['open-modal'].csrf_token }}
{{ meal[item]['open-modal'].submit( **{ 'class':'btn btn-primary',
'data-toggle':'modal',
'data-target':'#myModal-' +
item|string } ) }}
</form>
Keep in mind that this is nested inside of two for loops in jinja2.
{% for meal in menu_dict %}
{% for item in meal %}
....
{% endfor %}
{% endfor %}
The point is summarized with this, basically:
'data-target':'#myModal-' + item|string
adds the postfix.

Modify django templates to check for values in a dict

I have the following Django template.
{% load custom_tags %}
<ul>
{% for key, value in value.items %}
<li> {{ key }}: {{ value }}</li>
{% endfor %}
I need to check for the value and do some modifications.
If the value is True , instead of value I have to print Applied , else if it False I need to print Not Applied.
How to achieve that?
Very simple if-else clause here. Take a look at the django template docs to familiarize yourself with some of the common tags.
{% if value %}
APPLIED
{% else %}
NOT APPLIED
{% endif %}
You asked how to do this as a filter... I'm not sure why, but here is it:
In your app's templatetags directory create a file called my_tags.py or something and make the contents
from django import template
register = template.Library()
#register.filter
def applied(value):
if value:
return 'Applied'
else:
return 'Not applied'
Then in your template make sure to have {% load my_tags %} and use the filter with {{ value|applied }}

How to use django template dot notation inside a for loop

I am trying to retrieve the value of a dictionary key and display that on the page in a Django template:
{% for dictkey in keys %}
<p> {{ mydict.dictkey }} </p>
{% endfor %}
(let's say 'keys' and 'mydict' have been passed into the template in the Context)
Django renders the page but without the dictionary contents ("Invalid template variable")
I assume the problem is that it is trying to do mydict['dictkey'] instead of mydict[actual key IN the variable dictkey]? How does one "escape" this behavior?
Thanks!
UPDATE:
Based on the answers received, I need to add that I'm actually looking specifically for how to achieve a key lookup inside a for loop. This is more representative of my actual code:
{% for key, value in mydict1.items %}
<p> {{ mydict2.key }} </p>
{% endfor %}
Basically, I have two dictionaries that share the same keys, so I can't do the items() trick for the second one.
See this answer to a (possibly duplicate) related question.
It creates a custom filter that, when applied to a dictionary with a key as it's argument, does the lookup on the dictionary using the key and returns the result.
Code:
#register.filter
def lookup(d, key):
if key not in d:
return None
return d[key]
Usage:
{% for dictkey in dict1.keys %}
<p> {{ dict2|lookup:dictkey }} </p>
{% endfor %}
Registering the filter is covered in the documentation.
I find it sad that this sort of thing isn't built in.
From http://docs.djangoproject.com/en/dev/ref/templates/builtins/#for
This can also be useful if you need to access the items in a dictionary. For example, if your context contained a dictionary data, the following would display the keys and values of the dictionary:
{% for key, value in data.items %}
{{ key }}: {{ value }}
{% endfor %}
The trick is that you need to call dict.items() to get the (key, value) pair.
See the docs: http://docs.djangoproject.com/en/dev/ref/templates/builtins/#for
{% for key, value in data.items %}
{{ key }}: {{ value }}
{% endfor %}

Categories

Resources