Determining if I need quotes in HTML with django template - python

I have a dict in python that is something like the following:
d = {'key1': .98, 'key2': 'some_str',
#...
}
In this dictionary some keys will be mapped to float and others will be mapped to str
In my HTML I am doing something like the following:
html_dict = {
{% for k, v in my_dict.items %}
{{ k }}: "{{ v }}",
{% endfor %}
};
However this approach wraps the floats in quotes as well, which is what I don't want. But if I don't know wrap them in quotes the HTML doesn't understand that they are are string values. I would ideally like something like the following:
html_dict = {
{% for k, v in my_dict.items %}
{% if check_v_is_str %}
{{ k }}: "{{ v }}",
{% else %}
{{ k }}: {{ v }},
{% endif %}
{% endfor %}
};

Don't do this. You are manually trying to replicate a JS data structure, when there already exists a well-defined structure that both Python and JS know about, namely JSON. Use that instead. Convert the dict to JSON in your view, and pass it to the template where it can be output directly.

You could define a filter called "check_v_type" to call in your template as follows:
{% if v|check_v_type == 'str' %}
But I don't think that makes for good logic. Generally, you want to avoid function calls in your templates. Instead, in your view, you could create a dictionary of tuples of the form:
d = {'key1': (.98, False), 'key2': ('some_str', True), #...}
You could then use the boolean in each tuple to decide how to format the value in your HTML.

Related

Is there a generic, recursive flask template?

As a way to rapidly prototype an html ui, I am looking for a generic jinja2 template, that will display an object's or dictionary name/value pairs recursively, including drilling into sub objects recursively.
So say I had this dictionary:
a_dict = {'name1': 'value1', 'name2': 'value2'}
a_dict['other'] = {'name3': 'value3', 'name4': 'value4'}
It would display something like this:
name1: value1
name2: value2
other:
name3: value3
name4: value4
{% macro show_node(node) %}
{% for key, value in node.__dict__.items() %}
<span>{{key}}: </span>
{% if value is mapping %} <-- not sure what to do here
{{ show_node(value) }}
{%else%}
<span>Value: {{value}}</span>
{% endif %}
{% endfor %}
{% endmacro %}
there you go

Django template and part of a dictionary of lists

in Django I want to display some entries in a dictionary of lists.
My context is:
keys = ['coins', 'colors']
dict = {'colors':['red', 'blue'],
'animals':['dog','cat','bird'],
'coins':['penny','nickel','dime','quarter'] }
Template code:
<ul>{% for k in keys %}
<li>{{ k }}, {{ dict.k|length }}: [{% for v in dict.k %} {{ v }}, {% endfor %}]
{% endfor %}</ul>
I want to see:
* coins,4: [penny, nickel, dime, quarter,]
* colors,2: [red, blue,]
But what I actually see is keys but no values:
* coins,0: []
* colors,0: []
Note: I also tried dict.{{k}} instead of dict.k, but as expected that just gave a parse error in template rendering. I'll get rid of the trailing comma with forloop.last after getting the basic list working.
What is the secret sauce for displaying selected values from a dictionary of lists?
The question django template and dictionary of lists displays an entire dictionary, but my requirement is to display only a few entries from a potentially very large dictionary.
The problem (as you suspected) is that dict.k is evaluated to dict['k'] where 'k' is not a valid key in the dictionary. Try instead to iterate each item pair using dict.items and only display the results for the keys you're concerned with:
<ul>{% for k, v in dict.items %}
{% if k in keys %}
<li>
{{ k }}, {{ v|length }}: [{% for val in v %} {{ val }},{% endfor %}]
</li>
{% endif %}
{% endfor %}
</ul>
<ul>
{% for k, v in dict.items %} # instead of iterating keys, iterate dict
{% if k in keys %} # if key found in keys
<li>
{{ k }}, {{ v|length }}: [{% for val in v %} {{ val }},{% endfor %}]
</li>
{% endif %}
{% endfor %}
</ul>

Django: templates and iterate over dict

I have a dict:
>>> some_dict
{1: ['String1', 'String2', 'String3','String4' ],
2: ['String1_2', 'String2_2', 'String3_2', 'String4_2' ],}
In my template i want to iterate over this dict and display values in html. So i sent this dict from view:
return render_to_response('tournament.html',
{.....
'some_dict' : some_dict,
'some_dict_range' : range(4),
.....
})
In tournament.html i trying to iterate over some_dict. I want to get output that should looks like:
'String1', 'String2', 'String3','String4'
{% for iter1 in some_dict_range%}
{{some_dict.0.iter1}}<br>{% endfor %}
And as result, i get nothing.
But when i trying to get same result without iterator:
some_dict.0.0, some_dict.0.1, etc. i get what i need ('String1', 'String2', 'String3','String4').
And when i trying to view values of "iter1" i get the right digits:
{% for iter1 in some_dict_range%}
{{iter1}}<br> {% endfor %}
0, 1, 2 ...
Why this doesn't work this way? And if i wrong in design of this, how it should looks like? I mean - what the right way to iterate over this dict and display values in html-template?
Shouldn't:
{{some_dict.0.iter1}}<br>{% endfor %}
Be:
{{some_dict.iter1.0}}<br>{% endfor %}
^^^^^^^
Else you're trying to access some_dict[0] which isn't present...
To avoid passing in the range (as I assume you're wanting to output the dict in key order), you can use the following:
{% for k, v in some_dict.items|sort %}
Position {{ k }} has a first value of {{ v.0 }} and has:<br>
{{ v|join:"<br/>" }}
{% for item in v %}
{{ item }}
{% endfor %}
{% endfor %}

Having problems iterating over dict in Django template

There seem to be a million questions (and answers) about this, but none of them are working for me.
I've got something like this:
test_dict = {'name':'Joe'}
return render_to_response('home.html',test_dict,context_instance=RequestContext(request))
In the template, I'm trying to do this:
{% for k,v in test_dict.items %}
Hello {{ v }} <br />
{% endfor %}
But no luck. On the other hand, this works:
Hello {{ name }}
(No for loop). I must be missing something really obvious?
EDIT
In response to the first answer, I've also tried this:
test_dict = {'name':'Joe'}
data = {'test_dict':test_dict}
return render_to_response('home.html',data,context_instance=RequestContext(request))
And in the template:
{% block content %}
{% for k, v in data.items %}
Hello {{ v }} <br />
{% endfor %}
{% endblock %}
Still nothing showing up.
To do what you want, you would want something like
data = {'test_dict':test_dict}
return render_to_response('home.html',data,context_instance=RequestContext(request))
From the docs
A dictionary of values to add to the template context.
So in your example, test_dict is injected into the template context. Think of it working like this:
template = Template()
for k, v in dictionary.items():
template[k] = v
So test_dict is not injected into the template's context, but the keys and values of test_dict are.
When:
test_dict = {'name':'Joe'}
data = {'test_dict':test_dict}
return render_to_response('home.html',data,context_instance=RequestContext(request))
Use:
{% for k, v in test_dict.items %}

Can't iterate over nestled dict in django

Im trying to iterate over a nestled dict list. The first level works fine. But the second level is treated like a string not dict.
In my template I have this:
{% for product in Products %}
<li>
<p>{{ product }}</p>
{% for partType in product.parts %}
<p>{{ partType }}</p>
{% for part in partType %}
<p>{{ part }}</p>
{% endfor %}
{% endfor %}
</li>
{% endfor %}
It's the {{ part }} that just list 1 char at the time based on partType. And it seams that it's treated like a string. I can however via dot notation reach all dict but not with a for loop. The current output looks like this:
Color
C
o
l
o
r
Style
S
.....
The Products object looks like this in the log:
[{'product': <models.Products.Product object at 0x1076ac9d0>, 'parts': {u'Color': {'default': u'Red', 'optional': [u'Red', u'Blue']}, u'Style': {'default': u'Nice', 'optional': [u'Nice']}, u'Size': {'default': u'8', 'optional': [u'8', u'8.5']}}}]
What I trying to do is to pair together a dict/list for a product from a number of different SQL queries.
The web handler looks like this:
typeData = Products.ProductPartTypes.all()
productData = Products.Product.all()
langCode = 'en'
productList = []
for product in productData:
typeDict = {}
productDict = {}
for type in typeData:
typeDict[type.typeId] = { 'default' : '', 'optional' : [] }
productDict['product'] = product
productDict['parts'] = typeDict
defaultPartsData = Products.ProductParts.gql('WHERE __key__ IN :key', key = product.defaultParts)
optionalPartsData = Products.ProductParts.gql('WHERE __key__ IN :key', key = product.optionalParts)
for defaultPart in defaultPartsData:
label = Products.ProductPartLabels.gql('WHERE __key__ IN :key AND partLangCode = :langCode', key = defaultPart.partLabelList, langCode = langCode).get()
productDict['parts'][defaultPart.type.typeId]['default'] = label.partLangLabel
for optionalPart in optionalPartsData:
label = Products.ProductPartLabels.gql('WHERE __key__ IN :key AND partLangCode = :langCode', key = optionalPart.partLabelList, langCode = langCode).get()
productDict['parts'][optionalPart.type.typeId]['optional'].append(label.partLangLabel)
productList.append(productDict)
logging.info(productList)
templateData = { 'Languages' : Settings.Languges.all().order('langCode'), 'ProductPartTypes' : typeData, 'Products' : productList }
I've tried making the dict in a number of different ways. Like first making a list, then a dict, used tulpes anything I could think of.
Any help is welcome!
Bouns: If someone have an other approach to the SQL quires, that is more then welcome. I feel that it kinda stupid to run that amount of quires. What is happening that each product part has a different label base on langCode.
..fredrik
Iterating over a dict yields the keys. You want either the iteritems() or itervalues() method.
{% for partName, partType in product.parts.iteritems %}
<p>{{ partName }}</p>
{% for part in partType %}
<p>{{ part }}</p>
{% endfor %}
....

Categories