7

I am trying to iteratively concatenate a string to build url params with a 'for' loop, but I believe I am having scoping issues.

The output should be: url_param = "&query_param=hello&query_param=world"

array_of_objects = [{'id':'hello'},{'id':'world'}]

{% set url_param = "" %}

{% set array_of_ids = array_of_objects|map(attribute='id')|list%} // correctly returns [1,2]

{% for id in array_of_ids %}
   {% set param = '&query_param='~id %}
   {% set url_param = url_param~param %}                             
{% endfor %}

//url_param is still an empty string

I also tried namespace(), but to no avail:

{% set ns = namespace() %}
 {% set ns.output = '' %}
 {% set array_of_ids = array_of_objects|map(attribute='id')|list%} // correctly returns [1,2]
{% for id in array_of_ids %}
   {% set param = '&industries='~id%}
   {% set ns.output = ns.output~param %}                             
{% endfor %}
//ns.output returns namespace
Brandi
  • 161
  • 1
  • 10

2 Answers2

9

That is indeed a scope issue. One "hacky" way of dealing with this is using a list that you append to like so:

{% set array_of_objects = [{'id':'hello'},{'id':'world'}] %}

{% set array_of_ids = array_of_objects|map(attribute='id')|list%}

{{ array_of_ids|pprint }} {# output: ['hello', 'world'] #}

{% set ids = [] %}  {# Temporary list #}

{% for id in array_of_ids %}
   {% set param = '&query_param='~id %}
   {% set url_param = url_param~param %}
   {{ ids.append(url_param) }}
{% endfor %}

{{ ids|pprint }} {# output: [u'&query_param=hello', u'&query_param=world'] #}
{{ ids|join|pprint }} {# output: "&query_param=hello&query_param=world" #}

The above gets you what you need, but for this specific example I would take a look at using jinja's join filter. It's more declarative and feels a little less hacky.

{% set array_of_objects = [{'id':'hello'},{'id':'world'}] %}

{# set to a variable #}
{% set query_string = "&query_param=" ~ array_of_objects|join("&query_param=", attribute="id") %}

{{ query_string|pprint }}
{# output: u'&query_param=hello&query_param=world'  #}

{# or just use it inline #}
{{ "&query_param=" ~ array_of_objects|join("&query_param=", attribute="id") }}
WoodyWoodsta
  • 160
  • 2
  • 15
Dylan Moore
  • 530
  • 2
  • 8
  • 1
    Thanks, Dylan! Your second solution worked great! I did not know join took multiple arguments. The First Solution works without {% set url_param = url_param~param %}, but I'm sure that was a typo. I actually tried a similar solution but thought I had to call 'do' when appending the array. – Brandi Dec 12 '18 at 15:51
1

You should change the initialization of your namespace. Here is an example from the docs that will help you out:

{% set ns = namespace(found=false) %}
{% for item in items %}
    {% if item.check_something() %}
        {% set ns.found = true %}
    {% endif %}
    * {{ item.title }}
{% endfor %}
Found item having something: {{ ns.found }}
b0lle
  • 732
  • 6
  • 19
  • IMHO this is the best answer. No hacks, just use language features. @Brandi: all you need in your second solution is to set "ns" as "namespace(output)". – MastroGeppetto Dec 28 '22 at 16:53