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>
Related
This is my code:
<!-- Loop thru Table Macro begins-->
{% macro loopThruTable(currentParent, prod)%}
<li> {{prod.category_name}} </li>
{% set currentParent = prod.id %}
{{ checkParent(currentParent) }}
<ul>
<table>
<tr>
<th>Service</th>
<th>Price</th>
</tr>
{{ checkParentService(currentParent)}}
</table>
</ul>
{% endmacro %}
<!-- Loop thru Table Macro ends-->
<!-- CheckParent Macro begin-->
{% macro checkParent(currentParent) %}
{% for prod in myProd %}
{% if prod.parent_category_id == currentParent %}
<ul>
{{ loopThruTable(currentParent, prod) }}
</ul>
{% endif %}
{% endfor %}
{% endmacro %}
<!-- checkParent Macro Ends-->
<!-- CheckParentService Macro begin-->
{% macro checkParentService(currentParent) %}
{% for serv in myServ %}
{% if serv.parent_category_id == currentParent %}
<tr>
{{ loopThruTableService(currentParent, serv.name) }}
{{ loopThruTableService(currentParent, serv.price) }}
</tr>
{% endif %}
{% endfor %}
{% endmacro %}
<!-- checkParent Macro Ends-->
<!-- Loop thru Table Macro begins-->
{% macro loopThruTableService(currentParent, blah) %}
<td>{{blah}}</td>
{% endmacro %}
<!-- Loop thru Table Macro ends-->
{% extends 'admin/master.html' %}
{% block body %}
<ul>
{% set parent = 0 %}
{{ checkParent(parent) }}
</ul>
{% endblock %}
for all intents and purposes it is running mostly correctly, but it is adding an extra table at the end of each loop.
enter image description here
as you can see in the bottom, there's a "ServicePrice" that is separating each category.
enter image description here
here's another example. I know it has to do with my loops, but as far as jinja2 is concerned, I don't know if there's a method that exists where i check if the parent just 'exists' in my object.
Thanks,
I figured it out.
I had to add one extra for loop and if statement in the loopThruTable Macro.
It now looks like this:
{% macro loopThruTable(currentParent, prod)%}
<li> {{prod.category_name}} </li>
{% set currentParent = prod.id %}
{{ checkParent(currentParent) }}
{% for serv in myServ %}
{% if serv.parent_category_id == currentParent %}
<table>
<tr>
<th>Service</th>
<th>Price</th>
</tr>
{{ checkParentService(currentParent)}}
</table>
{% endif %}
{% endfor %}
{% endmacro %}
I'm still not entirely sure why that works. But it works.
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 %}
I have a Django site that uses the below template to render a crispy-forms model formset. Using django-debug-toolbar, I gathered that the include tags are rendering the bootstrap4 templates many, many times. I think this is what is killing my performance (i.e. 3-4 minutes to load an inline formset with 100 forms in it)
How should I replace the include tags to avoid the duplicate rendering? Should I use extend somehow?
I can replace the include tags with the actual html from the bootstrap4 crispy-forms templates, but those templates have nested templates as well. That creates an exercising of building a master crispy-forms template that includes everything...which seems like the wrong way to go about this. In addition, I tried replace the bootstrap4/field.html include tag with the actual html, and field.html was still duplicated, and the data lost it's table structure because of the loss of with tag='td'.
{% load crispy_forms_tags %}
{% load crispy_forms_utils %}
{% load crispy_forms_field %}
{% specialspaceless %}
{% if formset_tag %}
<form {{ flat_attrs|safe }} method="{{ form_method }}" {% if formset.is_multipart %} enctype="multipart/form-data"{% endif %}>
{% endif %}
{% if formset_method|lower == 'post' and not disable_csrf %}
{% csrf_token %}
{% endif %}
<div>
{{ formset.management_form|crispy }}
</div>
<div class='table-responsive'>
<table{% if form_id %} id="{{ form_id }}_table"{% endif%} class="table table-hover table-sm" id='dispositionTable'>
<thead>
{% if formset.readonly and not formset.queryset.exists %}
{% else %}
<tr>
{% for field in formset.forms.0 %}
{% if field.label and not field|is_checkbox and not field.is_hidden %}
<th for="{{ field.auto_id }}" class="form-control-label {% if field.field.required %}requiredField{% endif %}">
{{ field.label|safe }}{% if field.field.required %}<span class="asteriskField">*</span>{% endif %}
</th>
{% endif %}
{% endfor %}
</tr>
{% endif %}
</thead>
<tbody>
{% for form in formset %}
{% if form_show_errors and not form.is_extra %}
{% include "bootstrap4/errors.html" %}
{% endif %}
<tr>
{% for field in form %}
{% include 'bootstrap4/field.html' with tag="td" form_show_labels=False %}
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% include "bootstrap4/inputs.html" %}
{% if formset_tag %}</form>{% endif %}
{% endspecialspaceless %}
I am trying to produce table headings using loop in flash but I get new lines after each:
{% extends "layout.html" %}
{% block title %}
Portfolio overview
{% endblock %}
{% block main %}
{% for variable in variables -%}
{% for key, value in variable.items() -%}
<table>
<thead><th>{{ key }}</th></thead>
{% endfor -%}
{% for key, value in variable.items() -%}
<tbody>
<td>{{ value }}</td>
</tbody>
{% endfor -%}
{%- endfor -%}
</table>
<h2>Cash available (US$): {{ cash }}</h2>
<h2>Total portfolio value (US$): {{ wealth }}</h2>
{% endblock %}
Result
However, I would like to get this
Desired result
Give this a shot;
{% extends "layout.html" %}
{% block title %}
Portfolio overview
{% endblock %}
{% block main %}
<table>
{% for variable in variables %}
<thead>
{% for key, value in variable.items() %}
<th>{{ key }}</th>
{% endfor %}
</thead>
<tbody>
{% for key, value in variable.items() %}
<td>{{ value }}</td>
{% endfor %}
</tbody>
{% endfor %}
</table>
<h2>Cash available (US$): {{ cash }}</h2>
<h2>Total portfolio value (US$): {{ wealth }}</h2>
{% endblock %}
I just fixed up the placement of your for loops.
I am trying to check a simple condition in Jinja Template inside for loop in a web page whether a number is divisible by three or not.
I have referred the following link
http://jinja.pocoo.org/docs/dev/templates/
(Note loop.index doesnt work for me forloop.counter does)
The code is
{% extends "header.html" %}
{% block content %}
<h1>List of all Reference Ids</h1>
<table class="table table-striped">
{% for master in object_list %}
{% if forloop.counter divisibleby 3 %}
Do something
{%endif%}
<td> {{ master.reference_id }} </td>
{% endfor %}
</table>
{% endblock %}
Tried various combinations such as below
{% if forloop.counter divisibleby 3 %}
{%endif%}
{% if forloop.counter divisibleby(3 %}
{%endif%}
{% if divisibleby(forloop.counter,3) %}
{%endif%}
{% if divisibleby forloop.counter 3 %}
{%endif%}
{% if forloop.counter%3==0 %}
{%endif%}
But nothing works. I dont know where I am making the mistake. Please help me out guys I am stuck into this problem for quite long.
template_string = """
{% for i in [1,2,3,4,5,6,7] %}
{% if loop.index %3 == 0%}3{%else%}0{%endif%}\n
{% endfor %}
"""
from jinja2 import Template
print Template(template_string).render()
although it sounds like you are using django Template not jinja ...
if this is DjangoTemplateLanguage then
{% if forloop.counter0|divisibleby:3 %}
should work (I think ... ) so in full here is the djangoTemplate equivelent that is runnable standalone
from django.template import Template, Context
from django.template.engine import Engine
from django.conf import settings
settings.configure(DEBUG=False)
template_string = """
{% for i in the_list %}
{% if forloop.counter|divisibleby:3 %}3{%else%}0{%endif%}\n
{% endfor %}
"""
print Template(template_string).render(Context({"the_list":[1,2,3,4,5,6,7]}))