Accessing dictionaries given django template's attributes? - python

So my problem is that I need to iterate over a dictionary given an attribute, which is the value of the for loop. For example, I have a dictionary called my_dictionary which is being iterated by a for loop in a django template, with an attribute called q. What I need is to access to that dictionary by using the q attribute. I tried with {{my_dictionary.q}}, {{my_dictionary.{{q}} }} but none of them did work. What can I do? I guess it should be similar as in Python my_dictionary[q]. Thank you.
Update: Actually, q has nothing to do with my_dictionary. Suppose that q is every element of a list [1,2,3] meanwhile my_dictionary is a dictionary with the following form: {1: ['a','b','c'], 2:['a'], 3:['c']}. So what I'm trying to do is access to each value of the dictionary given the values of the first list [1,2,3].

Suppose you return a dictionary from view to a template. Say your dictionary name is my_dictionary then in a template you need to do like this:
{% for q in my_dictionary %}
<p> {{ q.your_dictionary_key_name }} </p>
{% endfor %}
for iterating over list items in a dictionary
{% for key, value in dictionary.items %}
<li>{{value}}</li>
{% endfor %}

You could write a custom template filter:
from django.template.defaulttags import register
register = Library()
...
#register.filter
def get_item(dictionary, key):
# use .get so that if the key does not exist a KeyError will be raised
return dictionary.get(key)
usage in templates:
{% for q, value in my_dictionary.items %}
{{ my_dictionary.items|get_item:<key_variable_here> }}
{% endfor %}

Related

Using split in a django template

I have a dictionary passed to an html django template:
return render_to_response('showdata.html', context_instance=RequestContext(request, {'dictdati': context} ))
this dictionary has this structure:
{0: 'TO;DEC;1;2012/02/28 15:39:06.000;TO;1234;SI;DI;1234;TO;1\n', 1: 'TO;DEC;1;2012/02/28 15:39:06.000;TO;567;SI;DI;567;TO;1\n'}
and in an html template I need to print some of the values in the each row of the dict. If in a python file I use
for key,val in dictdati.items():
print val.split(';')[0]
it prints the first value correctly (TO) but in an html template
{% for key,val in dictdati.items %}
{{ val.split[0] }}
{% endfor %}
in the browser I receive the error:
TemplateSyntaxError at /getdata/
Could not parse the remainder: '[0]' from 'val.split[0]'
Can someone give me an idea to solve this problem?
you cant just call arbitrary logic in django... this is probably more of a job for the backend if you only want 0th but i think you can use the first filter
{{ my_var.split | first }}
I think I found solution so I made a custom Django filter
The Custom filter code:
from django import template
register = template.Library()
#register.filter
def get_index(value, arg):
return value[int(arg)]
And the HTML code:
{% for key,val in dict.items %}
{{ val|get_index:"0" }}
{% endfor %}
In get_index give the index number needed
Also, I see you have used string and then commas as values I have used it as a list so this code only works for value as list

Django - displaying values from a dictionary nested in a list in an html template

I have the followed class-based views in my views.py file:
class HomeView(TemplateView):
template_name = 'annual_means/home.html'
site_list = AnnualMean.objects.values("site").distinct()
def get_context_data(self, **kwargs):
context = super(HomeView, self).get_context_data(**kwargs)
context['sites'] = AnnualMean.objects.values("site").distinct()
return context
At the top of my html template, just for testing this out, I have {{sites}} and it is displaying:
Below, I have the following html code:
{% for value in sites %}
<li>{{value}}</li>
{% endfor %}
And it lists all the key:value pairs as shown above, e.g. {'site': 'Belfast Centre'}, instead of just the values. I assume this is due to the dictionary in the QuerySet being nested within a list. Is there a way I can return just the a dictionary or otherwise get around this problem?
I think you should use this as :
{% for value in sites %}
<li>{{value.site}}</li>
{% endfor %}
It will now print the values in list
You can access a key in a dictionary using the dot notation:
Dictionary lookup, attribute lookup and list-index lookups are implemented with a dot notation:
{{ my_dict.key }}
{{ my_object.attribute }}
{{ my_list.0 }}
For your code, that would be:
{% for value in sites %}
<li>{{value.site}}</li>
{% endfor %}

key and value of dictionary in html file Django [duplicate]

I would like to print out the number of votes that each choice got. I have this code in a template:
{% for choice in choices %}
{{choice.choice}} - {{votes[choice.id]}} <br />
{% endfor %}
votes is just a dictionary while choices is a model object.
It raises an exception with this message:
"Could not parse the remainder"
choices = {'key1':'val1', 'key2':'val2'}
Here's the template:
<ul>
{% for key, value in choices.items %}
<li>{{key}} - {{value}}</li>
{% endfor %}
</ul>
Basically, .items is a Django keyword that splits a dictionary into a list of (key, value) pairs, much like the Python method .items(). This enables iteration over a dictionary in a Django template.
you can use the dot notation:
Dot lookups can be summarized like
this: when the template system
encounters a dot in a variable name,
it tries the following lookups, in
this order:
Dictionary lookup (e.g., foo["bar"])
Attribute lookup (e.g., foo.bar)
Method call (e.g., foo.bar())
List-index lookup (e.g., foo[2])
The system uses the first lookup type
that works. It’s short-circuit logic.
To echo / extend upon Jeff's comment, what I think you should aim for is simply a property in your Choice class that calculates the number of votes associated with that object:
class Choice(models.Model):
text = models.CharField(max_length=200)
def calculateVotes(self):
return Vote.objects.filter(choice=self).count()
votes = property(calculateVotes)
And then in your template, you can do:
{% for choice in choices %}
{{choice.choice}} - {{choice.votes}} <br />
{% endfor %}
The template tag, is IMHO a bit overkill for this solution, but it's not a terrible solution either. The goal of templates in Django is to insulate you from code in your templates and vice-versa.
I'd try the above method and see what SQL the ORM generates as I'm not sure off the top of my head if it will pre-cache the properties and just create a subselect for the property or if it will iteratively / on-demand run the query to calculate vote count. But if it generates atrocious queries, you could always populate the property in your view with data you've collected yourself.
You need to find (or define) a 'get' template tag, for example, here.
The tag definition:
#register.filter
def hash(h, key):
return h[key]
And it’s used like:
{% for o in objects %}
<li>{{ dictionary|hash:o.id }}</li>
{% endfor %}
django_template_filter
filter name get_value_from_dict
{{ your_dict|get_value_from_dict:your_key }}
Similar to the answer by #russian_spy :
<ul>
{% for choice in choices.items %}
<li>{{choice.0}} - {{choice.1}}</li>
{% endfor %}
</ul>
This might be suitable for breaking down more complex dictionaries.
Ideally, you would create a method on the choice object that found itself in votes, or create a relationship between the models. A template tag that performed the dictionary lookup would work, too.
Could find nothing simpler and better than this solution. Also see the doc.
#register.filter
def dictitem(dictionary, key):
return dictionary.get(key)
But there's a problem (also discussed here) that the returned item is an object and I need to reference a field of this object. Expressions like {{ (schema_dict|dictitem:schema_code).name }} are not supported, so the only solution I found was:
{% with schema=schema_dict|dictitem:schema_code %}
<p>Selected schema: {{ schema.name }}</p>
{% endwith %}
UPDATE:
#register.filter
def member(obj, name):
return getattr(obj, name, None)
So no need for a with tag:
{{ schema_dict|dictitem:schema_code|member:'name' }}
You could use a namedtuple instead of a dict. This is a shorthand for using a data class. Instead of
person = {'name': 'John', 'age': 14}
...do:
from collections import namedtuple
Person = namedtuple('person', ['name', 'age'])
p = Person(name='John', age=14)
p.name # 'John'
This is the same as writing a class that just holds data. In general I would avoid using dicts in django templates because they are awkward.

Return items from RSS feed in Django Templatetags

Django noob here.
I'm trying to add RSS feed items into a django template using templatetags (with classytags).
Here's my code:
from django import template
from classytags.core import Tag
import feedparser
register = template.Library()
class ExampleTag(Tag):
name = 'exampletag'
def render_tag(self, context):
raw_feed = "example.com/feed.rss"
feed = feedparser.parse(raw_feed)
entrylist = {}
for entry in feed.entries:
entrylist[entry.title]
return entrylist
register.tag(ExampleTag)
Then, in the template I can call the ExampleTag with:
{% load my_tag %}
{% exampletag %}
This results in a KeyError at / u'The First Entry In The Feed'
If I change my code to append to a list, the template renders without error and the entire structured list is output in a single string.
This is what I'd like to do:
{% load my_tag %}
{% for item in exampletag %}
<p> {{ item }} </p>
{% endfor %}
However this just fails silently (obviously I'm not passing an interable object to the template)
Any ideas? Is this even a good way to go about doing this?
Thanks in advance.
This code looks highly suspect:
for entry in feed.entries:
entrylist[entry.title]
Shouldn't it be something like this?
for entry in feed.entries:
entrylist[entry.title] = entry # or some value
As it is right now you are trying to index into an empty dictionary and are thus getting a KeyError exception.
But I'm still not sure what you are trying to do. Here are 2 ideas that come to mind that may get you started.
Idea one: it sort of looks like you should write an inclusion tag.
Something like (untested):
#register.inclusion_tag('feed_entries.html'):
def feed_entries():
feed = feedparser.parse('example.rss')
return {'items': feed}
And in feed_entries.html
{% for item in items %}
<p> {{ item }} </p>
{% endfor %}
Then, in some random template where you want the list of items displayed:
{% load feed_tags %}
...
<p>Here are the latest entries:</p>
{% feed_entries %}
...
This is assuming feed contains a list of items you want to render somehow. Thus, whenever you use {% feed_entries %} in a template, your snippet of Python is called, it takes the returned dictionary and renders the feed_entries.html template, and the resulting HTML is placed wherever you wrote {% feed_entries %}.
Idea two: If you really want your tag to return a list of items, you could use an assignment tag:
#register.assignment_tag
def feed_entries():
return feedparser.parse('example.rss')
Then in your template you have to "catch" the result of this tag (the list of items):
{% feed_entries as items %}
{% for item in items %}
<p>{{ item }}</p>
{% endfor %}
But that means you'll have to duplicate the "as" and for-loop stuff in every template. The inclusion tag may save you typing and maintenance if you use it in many templates. But if you wanted to render the list differently in each template it would be more flexible. Say you want it in a list of <p> tags in one, but in a <ul> in another.

Can I access specific key values in dictionary from django template?

Is there any get() function for this instead?
{% for key, value in choices.items %}
<li>{{key}} - {{value}}</li>
{% endfor %}
From python I have the get() function to get values from a specific key. But I couldn't find a corresponding way to do that with django template tags. So I wonder is it possible?
I need to get specific values since using loops adds a lot of new lines in the html source.
Or should take care of the output inside the view before sending it out to the template, which method is better?
You can use {{ choices.items.key }} to access a specific dict element.
There is no reason to care about whitespace in the HTML code though; the typical end-user has no real business in reading it and if he's curious he an always use a DOM viewer or run it through a HTML beautifier.
If you want a specific value, just add it to the dotted-path:
{{ choices.items.somekey }}
will get you the value of choices.items['somekey'] if choices.items is a dict.
I think you are way advance now, just to share my point. you could do this way as well
{% for value in dict %}
{{value}}
{% endfor %}
or with key, value like
{% for key,value in dict.items %}
{{key}} : {{ value }}
{% endfor %}
If choices type is DICT like {}.
{{choices.somekey|default:""}}
If choices.items is DICT type.
{{choices.items.somekey|default:""}}
Try See little example.
# In Views.py
def dict_test(request):
my_little_dict = {"hi": "Hello"}
....
# in Template
{{my_little_dict.hi}}
You can specify as {{ choices.key_name }}
It worked for me. Just simple
{{ choices.values }}
This gives you a list of all the values in the dictionary at once.

Categories