How to set loop.index as a variable in Jinja - html

{% for data in data_list %}
{% set data_index = {{loop.index}} %}
for data_dict in data:
pass
In my inner loop, I need to use the loop index in the outer loop, so I intend to set it to a variable as above. But the syntax is invalid.
How to do that? Or is there another way to get the outer loop index?

i think, you should not use Expressions({{..}}) inside statements ({%..%}), try this :
{% for data in data_list %}
{% set data_index = loop.index %}
for data_dict in data:
pass

You could use the built-in enumerate function for the same to get i as the variable and also use it in an inner loop if you want.
{% for i,data in enumerate(data_list) %}
{{ i }}
{% for j in range(i) %}
{% endfor %}
{% endfor %}
All you need to do is pass enumerate or whatever built-in python function you need as a parameter to the render template function as shown below
#app.get("/foo")
def foo():
return render_template("foo.html", enumerate=enumerate, range=range)

Related

Condition based on the three first letters of a string?

In my Jinja template, model.DataType value can be user defined or built in. My requirenement is if model.DataType start with the three letters ARR, then do a specific operation.
Example of values:
ARRstruct124
ARR_int123
ARR123123
CCHAR
UUINT
etc.
{% set evenDataType = model.eventDataType %}
{%if evenDataType | regex_match('^ARR', ignorecase=False) %}
// do the operation
{%else%}
// do the operation
{% endif %}
With this template, I am getting the error
{%if evenDataType | regex_match('^ARR', ignorecase=False) %}
jinja2.exceptions.TemplateAssertionError: no filter named 'regex_match'
There is indeed no regex_match filter in the Jinja builtin filters. You might have found some examples using it, but this is an additional filter provided by Ansible, so it won't work outside of Ansible.
This said, your requirement does not need a regex to be fulfilled, you can use the startswith() method of a Python string.
So, you template should be:
{% set evenDataType = model.eventDataType %}
{% if evenDataType.startswith('ARR') %}
`evenDataType` starts with 'ARR'
{% else %}
`evenDataType` does not starts with 'ARR'
{% endif %}

Feed Jinja list with results of SQL query

I'm new to DBT and Jinja and wondering if it is possible to dynamically define a list using a SQL query. Instead of manually declaring the items of the list like:
{% set myOrders = [123,234, 345, 456, 567] %}
Define the list with a SQL query, something like this:
{% set myOrders = SELECT DISTINCT OrderNum FROM OrdersTable ORDER BY OrderNum %}
Is this possible?
Thanks!
Yes! Not quite as you've written it, but this is supported.
First, a note that this is inherently difficult because DBT typically runs in two phases:
templates are compiled to make actual SQL queries (i.e. all the Jinja gets executed)
the compiled SQL queries are executed
But there is a construction, {% if execute %}, that allows you to defer compilation to the execution stage.
Straightforwardly adapting the example in the docs for your use case:
{% set my_orders_query %}
SELECT DISTINCT OrderNum
FROM {{ ref('OrdersTable') }}
ORDER BY OrderNum
{% endset %}
{% set rows = run_query(my_orders_query) %}
{% if execute %}
{# Return the first column #}
{% set myOrders = rows.columns[0].values() %}
{% else %}
{% set myOrders = [] %}
{% endif %}

How do I display a message in Jinja (flask) if there is no object data to display

I have an object in python views.py that references the events database table. When there is data, it displays the data in my html template, however, when there is no data, I cannot figure out the {% if %} function that would display the message "No data found."
I have tried Tadeck's post, but the is defined always seems to evaluate to true even if there is no data to display. Thank you for your help.
{% if events is defined %}
value of variable: {{ events }}
{% else %}
variable is not defined
{% endif %}
views.py
events = db.session.query(Eventdetails, Buyers).\
join(Buyers).\
filter(Eventdetails.events_id == event_id)
return render_template(
self.template_file, events=events, the_event=the_event,
event_id=event_id
)
You are passing events as the query. You want it to be the query results:
events = db.session.query(Eventdetails, Buyers).\
join(Buyers).\
filter(Eventdetails.events_id == event_id).all()
Things to try:
{% if events %}
{% if events|length > 0 %}
{% if events != [] %}
This will help you. When event have data then it will go inside the if condition otherwise else will be execute No data found.
{% if events %}
value of variable: {{ events }}
{% else %}
No data found.
{% endif %}

Whare are the difference between set and with in jinja

I am beginner in computer science and trying to use python flask framework to create a webserver.
In the tutorials, I have seen the below jinja usage in the HTML which are
{% set a = somefunction() %}
{% with a = somefunction() %}
May I know what are the differences? Thanks.
While you may use {% set %} to define a variable, the {% with %} statement additionally creates a new scope which can be ended using the {% endwith %} statement.
For example:
{% with myvar=1 %}
...
{% endwith %}
myvar will only be available before the corresponding endwith.
You can also use with to create a local scope:
{% with %}
{% set myvar=1 %}
...
{% endwith %}
myvar will only be available within the given scope.
You can find information about these statements here (the examples shown here were taken from there also).
Variables inside a {% with %} statement are restricted to that particular statement, while variables created via {% set %} are accessible from anywhere in the template (they are global).
>>> import jinja2
>>> t = jinja2.Template("{% set a = 'Global' %}{% with a = 'Local' %}{{ 'First a is ' + a +'\n' }}{% endwith %}{{ 'Second a is ' + a }}")
>>> print(t.render())
First a is Local
Second a is Global

Jinja2 for loop behaving similarly to with

I'd like to iterate over a set of objects and find the maximum of one particular attribute, however jinja2 ignores any action within an iterator on a variable declared outside of the iterator. For example:
{% set maximum = 1 %}
{% for datum in data %}
{% if datum.frequency > 1 %}
{% set maximum = datum.frequency %}
{% endif %}
{% endfor %}
{# maximum == 1 #}
datum.frequency is definitely greater than 1 for some datum in data.
EDIT (solution)
This is similar to this post, but there's a bit more to it. The following works and is very ugly.
{% set maximum = [1] %}
{% for datum in data %}
{% if datum.freq > maximum[-1] %}
{% if maximum.append( datum.freq ) %}{% endif %}
{% endif %}
{% endfor %}
{% set maximum = maximum[-1] %}
Have you considered writing a custom filter to return the highest value of a particular attribute within your collection? I prefer to minimize the amount of logic I use in Jinja2 templates as part of maintaining a 'separation of concerns'.
Here is a link to a very good example of how one can be written in python:
Custom jinja2 filter for iterator
Once you have your filter returning the value you need access it by using '|' like so:
{% set maximum = datum|filtername %}