Distinguish between types in jinja2 - python

I have a HTML/jinja2 template that I am using to display data in the form of a table.
The data for the table may come in different ways, and I want the template to be able to handle both types using if statements. the type(x) function in python does not work in this language.
an array of dictionaries (list of dictionaries)
an array of arrays (list of lists)
a part of the template:
{% block page_content %}
<input type="text" id="search" placeholder="Type to search">
<table id="table" class="table">
<tr style="white-space:nowrap;">
{% for h in headers %}
{% if h is string %}
<th>{{h}}</th>
{% else %}
<th>{{h[1]}}</th>
{% endif %}
{% endfor %}
</tr>
{%if data is "TYPE CHECK HERE"}
{% for row in data %}
{% if row != {} %} #ALTERNATIVELY, COULD DO A TYPE CHECK HERE
<tr style="white-space:nowrap;{% if row['bad'] %}background-color:rgba(255, 0, 0, 0.09);{% endif %}">
{% for h in headers %}
<td style="white-space:nowrap;">{{ row[h[0]] }}</td>
{% endfor %}
</tr>
{% endif %}
{% endfor %}
{% endblock %}
TL:DR What are the distinguishable types in jinja2? How do I check a variable's type?

It's better practice to keep as much as your logic code on the python side, before rendering jinja.
So transfer your data on the python side to a list of headers, and a nested list as your data:
render_template('test.html',
headers=['name', 'age',],
rows=[{'color': 'red', 'data': ['john', 84]},
{'color': 'green', 'data':['jacob', 45]}]
html:
<table>
<thead>
<tr>
{% for item in header %}
<th> {{ item }} </th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for row in rows %}
<tr style="colour: {{ row['color'] }}">
{% for cell in row['data'] %}
<td>{{cell}}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
I've also tried approaches similar to yours while learning, but in the end I found that this works best because it gives you the most flexibility over your data, and manipulating data on the python side is often quite straightforward. So not really an answer, just general advise.

You could look this link, there describe some valid types to compare. For instance, you could check is a dict, you try:
{% if type({'a':1,'b':2}) is mapping %}
print "Oh Yes!!"
{% else %}
print "Oh No!!!"
{% endif %}
You can nested whatever you need, but the right way here is migrate complex logic to controller.
PD: This example was taken from here. Thank you to #sean-vieira

my_var is list
my_var = []
my_var.insert(0, 'list')
my_var is str
my_var = '111'
to distinguish in jinja2
{% if my_var[0] == 'list' %}
list:
{% for i in my_var[1:] %}
{{ i }}
{% endfor %}
{% else%}
str: {{ my_var }}
{% endif %}

Related

nested block and for loop in a Jinja template block

Trying to use nested block and for loop in a Jinja template block setup.
{% block main %}
<table>
<tr>
<td>user id</td>
<td>user sec level</td>
</tr>
{% block main_nested_b scoped %}
{%
for user in list_users:
t_id_user = str(user[0][0])
t_sec_level = str(user[2][0])
%}
<tr>
<td>
<a href='/usersEdit?id_user={{ t_id_user }}' class='onwhite'>edit</a>
</td>
</tr>
{% endfor %}
{% endblock main_nested_b %}
{% endblock main %}
</table>
Error message:
jinja2.exceptions.TemplateSyntaxError: expected token 'end of statement block', got 't_id_user'
Help?
You can't treat Jinja syntax as Python syntax. It's not the same thing. Keep your for tag separate from assignment (set) tags:
{% for user in list_users %}
{% set t_id_user = user[0][0] %}
{% set t_sec_level = user[2][0] %}
Note that there isn't even a : at the end of the for ... in ... syntax! Also you don't need to call str() here, leave that to Jinja to convert to strings for you; anywhere you use {{ t_id_user }} or {{ t_sec_level }} the value will be converted to a string anyway.
Here is the complete template:
<table>
{% block main %}
{% block main_nested_b scoped %}
{% for user in list_users %}
{% set t_id_user = user[0][0] %}
{% set t_sec_level = user[2][0] %}
<tr>
<td>
<a href='/usersEdit?id_user={{ t_id_user }}' class='onwhite'>edit</a>
</td>
</tr>
{% endfor %}
{% endblock main_nested_b %}
{% endblock main %}
</table>

Django render() not passing variable to template?

def get_queryset(self):
...
#days = {day1 : [[FreetimeStart, FreetimeEnd], [[Meeting1Start, Meeting1End], ...]], ...}
days = {}
for i in range(len(compilation)):
days[daylist[i]] = compilation[i]
print(days)
return render(self.request, 'calendar.html', {"days":days})
Above (with nonrelevant code omitted) is a function from a Django view I've been writing. It's supposed to send the days dictionary over to the template calendar.html (shown below), but it's not- I've confirmed via the print(days) statement that days is being generated properly and that the function is being called. I'm not getting any errors, either.
{{ days }}
<table>
<tr>
{% for key in days %}
<th>
{{ key }}
</th>
{% endfor %}
</tr>
<tr>
{% for value in days.values %}
<td>
{% if value.0 %}
Free time: {{ value.0.0 }} to {{ value.0.1 }}
{% else %}
Free time: None
{% endif %}
</td>
{% endfor %}
</tr>
<tr>
{% for value in days.values %}
<td>
{% for meeting in value.1 %}
Meeting from {{ meeting.0 }} to {{ meeting.1 }}</br>
{% endfor %}
</td>
{% endfor %}
</tr>
</table>
What am I doing wrong here? There doesn't seem to be anything wrong with my render() arguments.

Looping dynamic content on bootstrap4 rows [duplicate]

I would like to display data, three columns per row during my for. I would like my result to look like the following:
<table>
<tr><td>VALUE1</td><td>VALUE2</td><td>VALUE3</td></tr>
<tr><td>VALUE4</td><<td>VALUE5</td><td>VALUE6</td></tr>
</table>
Anyone know how to do it?
Syntax Error
TemplateSyntaxError at /
'for' statements should use the format 'for x in y': for i in range(0, len(all_products_list), 3)
There's a divisibleby tag.
So you can do something (ugly) like:
<table><tr>
{% for field in form %}
<td>{{ field }}</td>
{% if forloop.last %}
</tr>
{% else %}
{% if forloop.counter|divisibleby:"3" %}
</tr><tr>
{% endif %}
{% endif %}
{% endfor %}
</table>
Alternatively, you could give your form class a table_print method that returns a html string (wrapped in mark_safe).
<table>
{% for i in range(0, len(stuff), 3) %}
<tr>
{% for j in range(3) %}
<td>{{ stuff[i+j] }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
Sorry misunderstood question.

Could not parse the remainder: '{{' from '{{'

I'm trying to create a simple page, which should display a table.
It suppose to have several rows and columns. But not every row should have the same amount of columns.
this my html code which is producing an error:
<html>
{% for count in machine_count %}
<tr>
<td>{{ count }}</td>
<td>Aufzugmotor</td>
{% for status in statuses %}
{{ status.machine_number}}
{% if count == {{ status.machine_number }} %}
<td class="tableCell">
<img class="imageClass" src={{ status.src }}>
</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</html>
statuses is a model and machine_number is a tuple of strings.
I'm not really getting the mistake I made.
Is it not possible to use the if-tag on a placeholder ?
{% if count == {{ status.machine_number }} %}
Should be:
{% if count == status.machine_number %}
{{...}} is only used for injecting variable contents to the final output. Omit them if you're using the variable in other situations.

How to for-loop three columns per row in Django/python?

I would like to display data, three columns per row during my for. I would like my result to look like the following:
<table>
<tr><td>VALUE1</td><td>VALUE2</td><td>VALUE3</td></tr>
<tr><td>VALUE4</td><<td>VALUE5</td><td>VALUE6</td></tr>
</table>
Anyone know how to do it?
Syntax Error
TemplateSyntaxError at /
'for' statements should use the format 'for x in y': for i in range(0, len(all_products_list), 3)
There's a divisibleby tag.
So you can do something (ugly) like:
<table><tr>
{% for field in form %}
<td>{{ field }}</td>
{% if forloop.last %}
</tr>
{% else %}
{% if forloop.counter|divisibleby:"3" %}
</tr><tr>
{% endif %}
{% endif %}
{% endfor %}
</table>
Alternatively, you could give your form class a table_print method that returns a html string (wrapped in mark_safe).
<table>
{% for i in range(0, len(stuff), 3) %}
<tr>
{% for j in range(3) %}
<td>{{ stuff[i+j] }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
Sorry misunderstood question.

Categories