Django template: How to use variables in an {% if x == y %} statement? - python

In a Djgano template I want to include a {% if x == y %} statement where both x and y are variables as follows:
<title>Category: {{category_id}}</title>
<select name="category_id">
{% for category in categories %}
<option value="{{category.id}}"
{% if category.id is category_id %} selected {% endif %}>{{category.id}} : {{category.name}}</option>
{% endfor %}
The {{category_id}} variable is set and in the context. It displays correctly if places outside of the {% if %}, but inside the {% if %} bracket does not work.
{% if category.id == category_id %}
does not work. I assume that in this case category_id is simply read as a non-variable.
{% if category.id is {{category_id}} %}
{% if category.id == {{category_id}} %}
Gives an error:
"Could not parse the remainder: '{{category_id}}' from '{{category_id}}'"
{% if category.id is category.id %}
Works, of course, but of course that means that everything in the loop will become "selected".

Related

How can we change the datatype for jsonb column?

I have a code where I'm flattening the jsonb column and I have created a macro for it. First, it takes three arguments model_name is the database from where I'm pulling the data,
and json_column is the column that has JSON info. Now when I transform this data and flat the result the datatype for all the fields is text. I think its because of this ->>
the operator which converts all values to string. I just want to change the type of the field to what it is. If it is a string then it's a string.
after flattening the jsonb this is what I get
{% macro flatten_json(model_name, json_column) %}
{% set survey_methods_query %}
SELECT DISTINCT(jsonb_object_keys({{json_column}})) as column_name
from {{model_name}}
{% endset %}
{% set results = run_query(survey_methods_query) %}
{% if execute %}
{# Return the first column #}
{% set results_list = results.columns[0].values() %}
{% else %}
{% set results_list = [] %}
{% endif %}
select
_airbyte_ab_id,
_airbyte_data,
{% for column_name in results_list %}
_airbyte_data ->>'{{ column_name }}' as {{ column_name }}{% if not loop.last %},{% endif %}
{% endfor %}
from {{model_name}}
{% endmacro %}

If statement Could not parse the remainder: '|' from '|"

I'm trying to use a filter inside of an if statement and whenever I do, I get the error below.
I have looked through for typos and wasn't able to catch anything.
Details.html (the template)
{% extends "dashboard/header.html" %}
{% block content %}
{% load custom_filts %}
<h1>{{ result }} <span class="badge badge-pill badge-info" style="background-color: {{ colour | hexify }}">{{ result | get_model_name }}</span></h1>
{% if result|get_model_name == "Fixture" %}
{% block fixture_data %}
{% endblock %}
{% elif result | get_model_name == "Cable" %}
{% block cable_data %}
{% endblock %}
{% elif result | get_model_name == "Adapter" %}
{% block adapter_data %}
{% endblock %}
{% endif %}
{% endblock %}
My custom filters
from django import template
register = template.Library()
#register.filter
def get_model_name(value):
return value.__class__.__name__
#register.filter
def hexify(value):
return "#" + value
When this is used, I get this error:
TemplateSyntaxError at /dashboard/detail/1
Could not parse the remainder: '|' from '|'

How to get the current index of for loop with jijna2?

Let's say that I have a code like:
{% for x in posts %}
<p>We are in item: {{ x }}</>
{% else %}
And I want to get the current index of the for loop to run an if loop, something like(logically):
{% for x in posts %}
{% if x.index = 0 %}
<p>We are in the first item!</p>
{% else %}
<p>We are in item: {{ x }}</>
{% endif %}
{% endfor %}
How to do it inside jijna2? (I use Python with Flask).
You can use loop.index inside the loop.
{% for x in posts %}
<p>We are in item number: {{ loop.index }}</>
{% else %}
Flask Template docs
You can use several loop related variables for that
http://jinja.pocoo.org/docs/dev/templates/#list-of-control-structures

django template - for loop over 2 querysets

I am getting 2 querysets from db:
all_locations = Locations.objects.all()[:5]
rating = Rating.objects.all()[:5]
return render_to_response('index.html',{'all':all_locations,'rating':rating},context_instance=RequestContext(request))
But I am stuck here, not knowing how to loop over these 2 querysets in one loop. this is being wrong:
{% if all and rating %}
{% for every in all and rating %}
{{every.locationname}}, {{every.rating_score}}
{% endfor %}
{% endif %}
You can try zip(all_locations, rating). It will produce a list of tuples. Then you can iterate over them in pairs. Here is an example: (demo)
all_locations = ['ca','ny','fl']
ratings = ['best','great','good']
for (l,r) in zip(all_locations,ratings):
print l+':'+r
Outputs
ca:best
ny:great
fl:good
I have also come across this problem. Now I've fixed it.
what I do is using
new=tuple(zip(queryset1,queryset2))
return render(request, 'template.html', {"n": new}).
in view.py.
In template.html, I use three for sentences which are list below.
{% for i in n %}
{% for j in i|slice:"0:1" %}
......operate queryset1
{% endfor %}
{% for z in i|slice:"1:2" %}
.....operate queryset2
{% endfor %}
{% endfor %}
It seems this method will fulfill your needs.
this might work:
{% with rating|length as range %}
{% for _ in range %}
{{ rating[forloop.counter] }}
{{ location[forloop.counter] }}
{% endfor %}
{% endwith %}
i'm not sure if rating|length will to the job... you might need to add rating|length|times' withtimes` filter defined as:
#register.filter(name='times')
def times(number):
return range(number)

How to increment a variable on a for loop in jinja template?

I would like to do something like:
variable p is from test.py which is a list ['a','b','c','d']
{% for i in p %}
{{variable++}}
{{variable}}
result output is:
1 2 3 4
You could use loop.index:
{% for i in p %}
{{ loop.index }}
{% endfor %}
Check the template designer documentation.
In more recent versions, due to scoping rules, the following would not work:
{% set count = 1 %}
{% for i in p %}
{{ count }}
{% set count = count + 1 %}
{% endfor %}
After 2.10, to solve the scope problem, you can do something like this:
{% set count = namespace(value=0) %}
{% for i in p %}
{{ count.value }}
{% set count.value = count.value + 1 %}
{% endfor %}
As Jeroen says there are scoping issues: if you set 'count' outside the loop, you can't modify it inside the loop.
You can defeat this behavior by using an object rather than a scalar for 'count':
{% set count = [1] %}
You can now manipulate count inside a forloop or even an %include%. Here's how I increment count (yes, it's kludgy but oh well):
{% if count.append(count.pop() + 1) %}{% endif %} {# increment count by 1 #}
Or...
{% set count = [] %}
{% for something-that-loops %}
{% set __ = count.append(1) %}
<div> Lorem ipsum meepzip dolor...
{{ count|length }}
</div>
{% endfor %}
(From comments by #eyettea and #PYB)
Here's my solution:
Put all the counters in a dictionary:
{% set counter = {
'counter1': 0,
'counter2': 0,
'etc': 0,
} %}
Define a macro to increment them easily:
{% macro increment(dct, key, inc=1)%}
{% if dct.update({key: dct[key] + inc}) %} {% endif %}
{% endmacro %}
Now, whenever you want to increment the 'counter1' counter, just do:
{{ increment(counter, 'counter1') }}
if anyone want to add a value inside loop then you can use this its working 100%
{% set ftotal= {'total': 0} %}
{%- for pe in payment_entry -%}
{% if ftotal.update({'total': ftotal.total + 5}) %}{% endif %}
{%- endfor -%}
{{ftotal.total}}
output = 5
Came searching for Django's way of doing this and found this post. Maybe someone else need the django solution who come here.
{% for item in item_list %}
{{ forloop.counter }} {# starting index 1 #}
{{ forloop.counter0 }} {# starting index 0 #}
{# do your stuff #}
{% endfor %}
Read more here:
https://docs.djangoproject.com/en/1.11/ref/templates/builtins/
I was struggle with this behavior too. I wanted to change div class in jinja based on counter. I was surprised that pythonic way did not work. Following code was reseting my counter on each iteration, so I had only red class.
{% if sloupec3: %}
{% set counter = 1 %}
{% for row in sloupec3: %}
{% if counter == 3 %}
{% set counter = 1 %}
{% endif %}
{% if counter == 1: %}
<div class="red"> some red div </div>
{% endif %}
{% if counter == 2: %}
<div class="gray"> some gray div </div>
{% endif %}
{% set counter = counter + 1 %}
{% endfor %}
{% endif %}
I used loop.index like this and it works:
{% if sloupec3: %}
{% for row in sloupec3: %}
{% if loop.index % 2 == 1: %}
<div class="red"> some red div </div>
{% endif %}
{% if loop.index % 2 == 0: %}
<div class="gray"> some gray div </div>
{% endif %}
{% endfor %}
{% endif %}
Just to shed more light into this problem.
Jinja2 variables behaves differently from that of conventional scripting languages, you can't modify the variable in a for loop.Hence to bypass this behaviour you can use a dictionary, since you can change the value of the dictionary.
**{% set margin={"margin_value":0} %}**
{% for lang in language %}
<ul>
<li style="margin-right: {{ margin.margin_value}}px">{{ lang }}</li>
</ul>
**{% if margin.update({"margin_value":margin.margin_value + 2}) %}
{% endif %}**
{% endfor %}
In the above code the value of the dictionary is being modified.

Categories

Resources