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 )
Related
I'm trying to add some values from another list synchronously in the for loop of django ’s template. When I use a given number everything works fine, but when I replace it to {{forloop.counter}} it reports an error slice requires 2 arguments, 1 provided
I Googled it and the suggestion is that there should be no spaces in the code, but there are no spaces in my code, here the code in question.
{% for i in invtypes %}
<li>
...
<p>{{data|slice:":{{forloop.counter}}"}}</p>
</li>
{% endfor %}
The {{data}} is a list of extra data for invtypes so they have same length and sort。
I added a colon after slice to fix the error.
Before:
{{ post.body|slice":200" }}
After:
{{ post.body|slice:":200" }}
The problem is that in the line {{data|slice:":{{forloop.counter}}"}} the ":{{forloop.counter}}" would not work as you expect as if it were performing string interpolation. What can be done to get around this is to use the with template tag along with the add and stringformat template filters to get the required value as a template variable before you try to render that:
{% for i in invtypes %}
<li>
...
{% with str_counter=forloop.counter|stringformat:"i" %}
{% with slice_var=":"|add:str_counter %}
<p>{{ data|slice:slice_var }}</p>
{% endwith %}
{% endwith %}
</li>
{% endfor %}
One should also note that a need to do this implies that the view is not supplying the data to the template in an efficient manner, ideally the template should not be doing all of this manipulation with data. It can be seen that invtypes and data have some type of relationship but the context given by the view does not convey that at all.
I had the same problem and the solutions seems to be spaces indeed.
Try:
{% for i in invtypes %}
<li>
...
<p>{{ data|slice:":{{ forloop.counter }}" }}</p>
</li>
{% endfor %}
and see how that goes.
I found the correct solution.
(Wrong) =>
{{data|slice: ":{{forloop.counter}}"}}
[don't add a space after slice's colon.
(Right) =>
{{data|slice:":{{forloop.counter}}"}}
If you add a space after slice's colon, it takes only the part which comes before that space and considered it as one argument and second one will be considered as missing.
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 :/
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.
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 %}
I want to define a variable if a condition is met:
{% if order_item.status.ordering >= 60 and is_client %}
{% with readonly=1 %}
{% else %}
{% with readonly=0 %}
{% endif %}
...some code
{% endwith %}
However, I get the following error:
Invalid block tag: 'else', expected 'endwith'
How can I fix this bug in django?
Perhaps it's better to add a readonly property/method to your order_item.status.
Alternatively you could also try a templatefilter or templatetag.
This code doesn't make any sense, first you should learn the with syntax. You have opened it twice and closed once and you don't have any useful code inside with.