1

I use a custom Widget to modify the context for the widget template (add more information).

Context:

'selected': [[3, 9], [3, 4, 7, 6]], 'depth_levels': {0: [{'name': 'Category A', 'value': 3, 'depth': 0, 'parent_id': None, 'children': [4, 9]}, {'name': 'Category B', 'value': 8, 'depth': 0, 'parent_id': None, 'children': []}], 1: [{'name': 'Category A_1', 'value': 4, 'depth': 1, 'parent_id': 3, 'children': [5, 7]}

{% for path in widget.selected %}
        {% for selected in path %}

            {% for level in widget.depth_levels.forloop.counter0 %}
                {{ level }}

            {% endfor %}
        {% endfor %}
    {% endfor %}

First I cycle thru the selected(path) and the internal arrays(selected). I want to use the {{forloop.counter0}} as a key for depth_levels.

The issue: {{widget.depth_levels.forloop.counter0}} doesn't return anything.

The forloop.counter is not used as index for a list, but it is used as key to a dictionary.

Using '.' to access is the default way in which Django templates access a dictionary* Using '0', '1' - {{widget.depth_levels.0}}- etc instead of forloop.counter0 it works.

Using a custom template tag again has an issue because the access is inside a for and can't use {{}} inside:

{% for level in widget.depth_levels.forloop.counter0 %}

The keys that I need to access depth_levels are from 0 to the length of each array inside the selected, the 'path' array in the example.

The values in selected arrays tell me later where to add attributes are not related to the keys of depth_levels.

My end goal is to access the name, value in the dictionaries that are in the array.

user3541631
  • 3,686
  • 8
  • 48
  • 115
  • [This](https://stackoverflow.com/questions/2376511/how-to-access-outermost-forloop-counter-with-nested-for-loops-in-django-template) might help – Laur Ivan Nov 24 '17 at 10:22
  • 1
    Possible duplicate of [Reference list item by index within Django template?](https://stackoverflow.com/questions/4651172/reference-list-item-by-index-within-django-template) – Sayse Nov 24 '17 at 10:24
  • 1
    ^see the second answer – Sayse Nov 24 '17 at 10:24
  • @Laur Ivan - my situation is different I don't need to access {{forloop.counter}} as default or his parent (I can do that no issues here) but to use it like a key for a dictionary – user3541631 Nov 24 '17 at 10:25
  • @Sayse The forloop.counter is not used as index for a list, but it is used as key to a dictionary(as in the other post). Using '.' to access is the default way in which Django templates access a dictionary, this is why I don't understand why it doesn't work. If I use '0', '1', not 'dynamic' it works – user3541631 Nov 24 '17 at 10:34
  • Why can't you use something like this: `{% for key, level in widget.depth_levels.items %}`? – Piyush Das Nov 24 '17 at 10:44
  • @Sayse - I checked the questions and answers and the situation is different, acces different structured , used inside {% for %} in my case, not outside, so is not a duplicate. – user3541631 Nov 24 '17 at 10:45
  • @Piyush Das I need to access specific keys not all, If you take a look at selected, you see that the lists inside have different length. Depending on the length of the list I know how many and which keys I access (this is why I need the foorloop.counter0 – user3541631 Nov 24 '17 at 10:47
  • Dictionary or list doesn't matter, its the same syntax and the same answer of make a custom template tag – Sayse Nov 24 '17 at 10:51
  • @Sayse - I understand that, I added more info – user3541631 Nov 24 '17 at 12:22

2 Answers2

2

You can add a filter like this (To know more: https://docs.djangoproject.com/en/1.11/howto/custom-template-tags/#writing-custom-template-filters):

@register.filter
def value_by_key(d, key):    
    return d[key]

Then use it like this:

% for path in widget.selected %}
    {% for level in widget.depth_levels|value_by_key:path|length %}
        {{ level }}
    {% endfor %}
{% endfor %}
  • The keys that I need are from 0 to the length of the each array inside the path, so the selected is not the key, this is why I need the {{forloop.counter}}. Compared to your example I also go one level deeper. – user3541631 Nov 24 '17 at 10:53
  • So you can use "forloop.counter" instead of "selected" (without inverted quotation) – Mahabubur Rahaman Melon Nov 24 '17 at 11:00
0

If your end goal is to access each name, value in the dictionaries that are in the array, then you should do something like this.

{% for path in widget.selected %}
    {% for selected in path %}
        {% for key, level in widget.depth_levels.items %}
            {% for key_obj in level %}
                {{ key_obj.name }}
                {{ key_obj.value }}
            {% endfor %}
        {% endfor %}
    {% endfor %}
{% endfor %}
Piyush Das
  • 610
  • 1
  • 7
  • 18
  • The keys that I need are from 0 to the length of the each array inside the path, so the selected is not the key, this is why I need the {{forloop.counter}}. The goal is to access names based on arrays in selected length, not necessary all of them. – user3541631 Nov 24 '17 at 11:18
  • Provide a sample output of what you want. It is very unclear from your question as to what you want. – Piyush Das Nov 24 '17 at 11:24