I'm passing 2 variables (3 including a simple one) to some Jinja from a python script.
On certain runs I want to generate a list with links.
<html>
<body>
<h1>{{ title }}</h1>
<table>
{% if packageURLs is defined %}
{% for x in packageURLs: %}
<a href="{{ x }}">
{% endfor %}
{% for i in packagesList: %}
<tr><td>{{ i }}</td></tr>
{% endfor %}
{" else "}
{% for i in packagesList: %}
<tr><td>{{ i }}</td></tr>
{% endfor %}
{% endif %}
</a>
</table>
</body>
for each 'packageURLs' I want to add a tag then some table tags for 'packages' List. What's happening though is its generating HTML but completing each individual for loop first. So I end up with half a page full of links then another with table rows. How can I have it iterate through both initially?
I found a solution:
<html>
<body>
<h1>{{ title }}</h1>
<table>
{% if packageURLs is defined %}
{% for i,x in packagesList %}
<a href="{{ x }}">
<tr><td>{{ i }}</td></tr>
</a>
{% endfor %}
{" else "}
{% for i in packagesList: %}
<tr><td>{{ i }}</td></tr>
{% endfor %}
{% endif %}
</table>
</body>
Which is populated using zip() in the python script:
f = t.render(title=dataType,packagesList=zip(Info,packageURLs),packageURLs=packageURLs)
I kept the last variable out of laziness as a check since I still want to only execute those different chunks sometimes.
Related
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>
I am wondering how to create a jinja2 template that would allow my to put my header into a variable where I can extend the base file and then call upon the header in my child file.
Currently my code for the parent is:
{% block head %}
<div class="wrapper col2">
<div id="topbar">
<div id="topnav">
<ul>
<ul>
<li>Home</li>
<li>Sign in/up</li>
<li>Admin console
<ul>
<li>Console</li>
<li>Staff Management</li>
<li>ALERTS</li>
<li>Sign up Shooters</li>
</ul>
</li>
<li >Contact Us</li>
<li class="last">logout</li>
</ul>
</div>
<br class="clear" />
</div>
<hr>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }} </li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
</div>
{% endblock %}
My child template is:
{% extends "Header.html" %}
{% block head %}
{% endblock %}
<h1>CREATE SHOOT</h1>
<form action="" method="post" name="form">
{{ form.hidden_tag() }}
<p>
<h2>Name of shoot:</h2>
{{ form.nameofshoot(size=40) }}<br>
<h2>Number of days in shoot:</h2>
{{ form.day}}
<p><input type="submit" value="Create Shoot"></p>
</form>
Am I doing something wrong or is there another approach I can take?
What you need to do is remove from your child template the lines {% block head %}{% endblock %}
Because in your child template you call {% extends "Header.html" %}, all of the content declared in Header.html (no matter what blocks it is in) will automatically be included. That's the job of extends.
By adding the {% block head %}{% endblock %} in your child template, what you have effectively said is "take everything from Header.html, but override everything in the 'head' block with what I specify in my child template". Then, because there is nothing in the block defined in your child template, you are replacing the content defined in your Header.html file with nothing.
You want to use the {% block blockname %} notation to specify what you want to change in the child template, not what you want to keep the same.
This page on inheritence is the relevant section of the Jinja documentation, and provides a nice example.
I am developing an application with python Django
what I need to do is to assign a class to a div based on the counter variable value in templates
{% with 1 as counters %}
{% for importance in all_importance %}
{% if counters == 1 %}
<div class="item active" >
{% else %}
<div class="item" >
{% endif %}
{% for image in importance.subtypemodelimage_set.all %}
<img src="{{ image.image.url }}" />
{% endfor %}
</div>
{% counters += 1 %}
{% endfor %}
{% endwith %}
But I face this issue
Invalid block tag: 'counters', expected 'empty' or 'endfor'
where am I making mistake, thanks in advance for your helps
The for loop sets a number of variables available within the loop (full list in django docs here):
...
forloop.first True if this is the first time through the loop
forloop.last True if this is the last time through the loop
...
you can use forloop.first to check for first loop iteration:
{% for importance in all_importance %}
{% if forloop.first %}
<div class="item active" >
{% else %}
<div class="item" >
{% endif %}
{% for image in importance.subtypemodelimage_set.all %}
<img src="{{ image.image.url }}" />
{% endfor %}
</div>
{% endfor %}
Problem is with
{% counters += 1 %}
There is not tag counters. You are interpreting variable as tag.
More over you can't implement that kind of for loop in django template.
I have the following loop in my Django template:
{% for item in state.list %}
<div> HTML (CUSTOMERS BY STATE) </div>
<!-- print sum of customers at bottom of list -->
{% if forloop.last %}
<h4>{{ forloop.counter }} Valued Customers</h4>
{% endif %}
{% endfor %}
Obviously, if I end up with only one customer, I'd like to print singular "Valued Customer"
According to Django's docs, one should use blocktrans. Tried the following, a few flavors of nesting:
{% blocktrans count %}
{% if forloop.last %}
<h4>
{{ forloop.counter }}
Valued Customer
{% plural %}
Valued Customers
</h4>
{% endif %}
{% endblocktrans %}
Keep getting TemplateSyntaxError: Invalid block tag: 'blocktrans', expected 'empty' or 'endfor'
Is there no way to combine with another loop? Any ideas how to solve? Thanks!
Here is the working code, thanks to alko:
{% load i18n %}
<!-- ... -->
{% if forloop.last %}
<h4>
{{ forloop.counter }}
{% blocktrans count count=forloop.counter %}
Valued Customer
{% plural %}
Valued Customers
{% endblocktrans %}
</h4>
{% endif %}
Probably, you forgot to load translation tags. Add following line at the top of your template:
{% load i18n %}
After you fix that, note that for a blocktrans tag after count a variable, whose value will serve for plural detection, should be specified, so you probably need something like
{% blocktrans count count=forloop.counter %}
To pluralize use this:
Customer{{ forloop.counter|pluralize }}
I read the docs and I am not clear on this is right at all. I know you can use nested for loops, but if statements seem to be different.
Can i do the following?
{% if thing=true %}
<div> something here</div>
{% if diffthing=true %}
<div> something else</div>
{% else %}
<div> third thing</div>
{% endif %}
{% else %}
<div> nothing here </div>
{% endif %}
Or should the format be different somehow?
Jinja2 supports nested blocks, including if statements and other control structures.
See the documentation on Block Nesting and Scope: "Blocks can be nested for more complex layouts."
A good use case for this is writing macros that conditionally output HTML:
{# A macro that generates a list of errors coming back from wtforms's validate function #}
{% macro form_error_summary(form, li_class='bg-danger') %}
{# only do the following on error... #}
{% if form.errors %}
<ul class="errors">
{# you can do layers of nesting as needed to render your content #}
{% for _field in form %}
{% if _field.errors %}
{% for error in _field.errors %}
<li class={{li_class}}>{{_field.label}}: {{ error|e }}</li>
{% endfor %}
{% endif %}
{% endfor %}
</ul>
{% endif %}
{% endmacro %}
The answer is yes.
I'm using logic very similar to yours in a live application and the nested if blocks work as expected. It can get a little confusing if you don't keep your code clean, but it works fine.
It seem possible. Refer to the documentation here: http://jinja.pocoo.org/docs/templates/#if
Just a quick add, if you're unpacking data to populate your fields, Jinja will only unpack it once. I had a similar problem with MongoDB and found if you change the item to a list item you iterate through it more than once without nesting
#app.route("/")
#app.route("/get_shrink")
def get_shrink():
# find and sort shrink top 5
shrink = list(mongo.db.shrinkDB.find().limit(5).sort(
"amount_lost_value", -1,))
return render_template(
"shrink.html", shrinkDB=shrink)
{% for shrink in shrinkDB %}
{% if shrink.resolved == true %}
<li>{{ shrink.product_name }} ||£ {{ shrink.amount_lost_value }} || {{ shrink.date }}</li>
{% endif %}
{% endfor %}
</span>
</div>
</div>
<div class="col s12 m5 offset-m2">
<h4>Top 5 Resolved Threats</h4>
<div class="card-panel light-blue">
<span class="white-text">
<!-- Shrink For loop top 5 resolves-->
{% for shrink in shrinkDB %}
{% if shrink.resolved != true %}
<li>{{ shrink.product_name }} ||£ {{shrink.amount_lost_value }} || {{ shrink.date }}</li>
{% endif %}
{% endfor %}