0

I'm trying to make a simple macro in jinja and then call it with {{messageRed('TEST')}}, but it does not work, no matter what i do. It also does not increment the counter to +1. In the end i just get the Output:

Compliance Score: 0

Expected Output: Compliance Score: 1 TEST

Here's the code:

{%set counter = 0 %}

{%set msgRed = ''%}

{%macro messageRed(msg) -%}
    {%set counter = counter + 1%}
    {%set msgRed = msgRed + '<p style="color: red;">' + msg + '</p>'%}
{%- endmacro%}

{{messageRed('TEST')}}

<h3>Compliance Score: <b> {{counter}} </b></h3><hr>{{msgRed}}
WiLL_K
  • 575
  • 1
  • 3
  • 22
MaxWasHere
  • 55
  • 1
  • 8
  • always put full error message (starting at word "Traceback") in question (not comment) as text (not screenshot, not link to external portal). There are other useful information. – furas Apr 30 '21 at 10:06
  • did you run it twice? Did you get `2 TEST`? I only guest: it may use local variable `counter` inside `messageRed` and it never use external `counter`. And probably it is always `0` when you run it - so if you run it many time you should always get text `1 TEST` – furas Apr 30 '21 at 10:09
  • base on information on internet it can be normal (and [documented](https://jinja.palletsprojects.com/en/2.11.x/templates/)) behavior - `scope` - macro can't access external variable. In answer to question [How to increment a variable on a for loop in jinja template?](https://stackoverflow.com/a/49699589/1832058) someone suggests to use `{% set count = namespace(value=0) %}` and later `{% set count.value = count.value + 1 %}` – furas Apr 30 '21 at 10:22

1 Answers1

0

Base on information on internet macro can't change external elements - and it is normal and documented behavior - look for scope.

So it not only can't change exteranl value but also if you run it few times then you always get the same value. Probably like in normal function it create this (local) variable again and again every time when you run macro.

In answer to question How to increment a variable on a for loop in jinja template? someone suggests to define it as

{% set count = namespace(value=0) %} 

and change value

{% set count.value = count.value + 1 %}

and display it

{{ count.value }}

And it works for me.

The same is with msgRed.

{%set msgRed = namespace(text="") %}

{%set msgRed.text = msgRed.text + '<p style="color: red;">' + msg + '</p>'%}

{{ msgRed.text }}

Here minimal working code which I used to test it: from jinja2 import Template

tm = Template("""
{%set counter = namespace(value=0) %}

{%set msgRed = namespace(text="") %}

{%macro messageRed(msg) -%}
    {%set counter.value = counter.value + 1%}
    {%set msgRed.text = msgRed.text + '<p style="color: red;">' + msg + '</p>'%}
{%- endmacro%}

{{messageRed('TEST')}}
<h3>Compliance Score: <b> {{counter.value}} </b></h3><hr>{{msgRed.text}}

{{messageRed('TEST')}}
<h3>Compliance Score: <b> {{counter.value}} </b></h3><hr>{{msgRed.text}}

{{messageRed('TEST')}}
<h3>Compliance Score: <b> {{counter.value}} </b></h3><hr>{{msgRed.text}}

""")

msg = tm.render()

print(msg)

Result

<h3>Compliance Score: <b> 1 </b></h3><hr><p style="color: red;">TEST</p>
    
<h3>Compliance Score: <b> 2 </b></h3><hr><p style="color: red;">TEST</p><p style="color: red;">TEST</p>
    
<h3>Compliance Score: <b> 3 </b></h3><hr><p style="color: red;">TEST</p><p style="color: red;">TEST</p><p style="color: red;">TEST</p>
furas
  • 134,197
  • 12
  • 106
  • 148