Jinja python for loop syntax - python

I have a jinja code for python and its giving me an error it doesn't give me in python
{% for i, juice in enumerate(a['juice'] for a in television):};
alert({{ juice }});
{% endfor %};
The Error I'm getting is
expected token ',', got 'for'

You don't need to add : at the end of the for statements in Jinja2. And, you are not properly closing the tag - missing the % before the }.
Plus, there is no enumerate() function in Jinja2, use the loop.index0:
{% for a in television %}
{{ loop.index0 }}, {{ a["juice"] }}
{% endfor %}
If you want to use more Python in the templates, you should probably look at the Mako engine.

Related

How to ignore special character in argument of render_template in Flask and HTML [duplicate]

I'm building an admin for Flask and SQLAlchemy, and I want to pass the HTML for the different inputs to my view using render_template. The templating framework seems to escape the HTML automatically, so all <"'> characters are converted to HTML entities. How can I disable that so that the HTML renders correctly?
To turn off autoescaping when rendering a value, use the |safe filter.
{{ something|safe }}
Only do this on data you trust, since rendering untrusted data without escaping is a cross-site scripting vulnerability.
MarkupSafe provides Jinja's autoescaping behavior. You can import Markup and use it to declare a value HTML safe from the code:
from markupsafe import Markup
value = Markup('<strong>The HTML String</strong>')
Pass that to the templates and you don't have to use the |safe filter on it.
From the Jinja docs section HTML Escaping:
When automatic escaping is enabled everything is escaped by default
except for values explicitly marked as safe. Those can either be
marked by the application or in the template by using the |safe
filter.
Example:
<div class="info">
{{data.email_content|safe}}
</div>
When you have a lot of variables that don't need escaping, you can use an autoescape override block:
{% autoescape false %}
{{ something }}
{{ something_else }}
<b>{{ something_important }}</b>
{% endautoescape %}
For handling line-breaks specifically, I tried a number of options before finally settling for this:
{% set list1 = data.split('\n') %}
{% for item in list1 %}
{{ item }}
{% if not loop.last %}
<br/>
{% endif %}
{% endfor %}
The nice thing about this approach is that it's compatible with the auto-escaping, leaving everything nice and safe. It can also be combined with filters, like urlize.
Of course it's similar to Helge's answer, but doesn't need a macro (relying instead on Jinja's built-in split function) and also doesn't add an unnecesssary <br/> after the last item.
Some people seem to turn autoescape off which carries security risks to manipulate the string display.
If you only want to insert some linebreaks into a string and convert the linebreaks into <br />, then you could take a jinja macro like:
{% macro linebreaks_for_string( the_string ) -%}
{% if the_string %}
{% for line in the_string.split('\n') %}
<br />
{{ line }}
{% endfor %}
{% else %}
{{ the_string }}
{% endif %}
{%- endmacro %}
and in your template just call this with
{{ linebreaks_for_string( my_string_in_a_variable ) }}
Use the safe filter in your template, and then sanitize the HTML with the bleach library in your view. Using bleach, you can whitelist the HTML tags that you need to use.
This is the safest, as far as I know. I tried both the safe filter and the Markup class, and both ways allowed me to execute unwanted JavaScript. Not very safe!

Could not parse the remainder: '{{ list[loop.index0] }}'

I followed instructions in simmilar thread like: How do you index on a jinja template?
but my html template is not working and whole django project is not responding due to this.
Error that I'm getting:
Error during template rendering.
Could not parse the remainder: '[loop.index0]' from 'songs_titles[loop.index0]'
My code looks like this:
{% if converted_files_urls %}
<p>Titles: {{ songs_titles }}</p>
{% for n in converted_files_urls %}
<a href="{{ n }}" download>Download: {{ songs_titles[loop.index0] }}</a>
<br/>
{% endfor %}
{% endif %}
and the {{ songs_titles }} renders as list, so at least till here it works ok.
What am I doing wrong?
Actually you are looking for Jinja, that will not work on django.
In django template tag you should use forloop.counter0 and list indexing looks like
{{songs_titles.1}}
Need to set count in variable and then use it, for setting variable you could use -
{% with index=forloop.counter0 %}
{{ songs_titles.index}}
{% endwith %}
Still If you have any doubts you can comment it.
I finally resolved this by creating a custom template tag like here:
https://djangosnippets.org/snippets/2740/
But to be honest it sucks that that's the simplest working solution for now :/

How to use forloop counter within curly braces in django?

I was trying to parse following object in my django template:-
obj=[{'abc1',123},{'abc2',234}]
I was trying the following code:-
{% for me in obj %}
{{ me{{forloop.counter}} }}
{% endfor %}
I need to use the forloop counter to get abc1, abc2 values. Its throwing following error:-
could not parse the remainder: '{{forloop.counter'
Any help?
you do not need inner {{...}} brackets - Django is parsing variables in outer brackets already.
Also if you need to concatenate two values you need to use add filter
Then it should be:
{% for me in obj %}
{{ me|add:forloop.counter }}
{% endfor %}

PyCharm Complaining about Django `templatetag` Argument

Here is a snippet of code in a template that uses a custom templatetag I wrote that does work:
{% if theme == 'books_literature' %}
{{ theme|prettify:'/' }}
{% else %}
{{ theme|prettify:' ' }}
{% endif %}
PyCharm is complaining about the colon and the characters after the colon, even though they are valid...
Here is an image showing what it looks like:
The hover I get says I should add closing curly braces... Which makes sense, if it wasn't expecting an argument.
#thebjorn reported it as PY-14890 ( https://youtrack.jetbrains.com/issue/PY-14890 )

How to dynamically add items to jinja variable in Flask?

I'm building a website using Flask with its jinja2 templating engine and I'm dynamically building the menu (as described here):
{%
set navigation_bar = [
('/', 'index', 'Home'),
('/aboutus/', 'aboutus', 'About Us'),
('/faq/', 'faq', 'FAQ')
]
%}
{% set active_page = active_page|default('index') -%}
<ul>
{% for href, id, title in navigation_bar %}
<li{% if id == active_page %} class="active"{% endif %}>
{{ title|e }}
</li>
{% endfor %}
</ul>
Now if a user is logged in I want to show some additional things. So at runtime I want to add items to the navigation_bar variable. I tried something like this:
{% if g.user.is_authenticated() %}
{% navigation_bar.append(('/someotherpage', 'someotherpage', 'SomeOtherPage')) -%}
{% endif %}
But unfortunately this results in the following error: TemplateSyntaxError: Encountered unknown tag 'navigation_bar'. Jinja was looking for the following tags: 'endblock'. The innermost block that needs to be closed is 'block'.
So: does anybody know how I can add additional items to a jinja2 variable at runtime? All tips are welcome!
[bonus question]
I was also wondering, what does the - do at the end of {% set active_page = active_page|default('index') -%}?
The error occurs because Jinja can't identify block. Each Jinja block should start from block name. do block from do extension meets your needs. To use it you should add
do extension to jinja extensions. You can do this like so:
app.jinja_env.add_extension('jinja2.ext.do')
And then you can use do extension. Your example should looks like this:
{% if g.user.is_authenticated() %}
{% do navigation_bar.append(('/someotherpage', 'someotherpage', 'SomeOtherPage')) %}
{% endif %}
Here's another simple example.
You will find answer to your bonus question here. In short - removes whitespaces from start or end of block (this depends on where it is located).
To complete the answer of Slava Bacherikov, if you don't have the Jinja "do extension", you can use the tag set:
{% if g.user.is_authenticated() %}
{# use a dummy variable name, we juste need the side-effect of method call #}
{% set _z = navigation_bar.append(('/someotherpage', 'someotherpage', 'SomeOtherPage')) %}
{% endif %}

Categories