3

I've a dict of dicts my_var defined as:

defaultdict(<class 'collections.Counter'>,{
    'product1': Counter({'total_qty': 1}),
    'product2': Counter({'total_qty': 13}),
    'product3': Counter({'total_qty': 65})
})

I pass it to the template with:

context = {'my_var': my_var}
return render(request, 'my_template.html', context)

In the template I try to print it without any luck:

<ul>
    {% for k in my_var %}
        <li>{{ k.component }}: {{ k.total_qty }}</li>
    {% endfor %}
</ul>

I get no error, but I don't get the keys and values; what am I doing wrong?

I get something like:

  • :
  • :
  • :

edit:

to add a bit of context, I initially have a list of dicts:

used_components = [{'total_qty': 5, 'component': 'component blue'},...]

then I use this function to group and sum dicts by key:

def solve(dataset, group_by_key, sum_value_keys):
    dic = defaultdict(Counter)
    for item in dataset:
        key = item[group_by_key]
        vals = {k: item[k] for k in sum_value_keys}
        dic[key].update(vals)
    return dic

my_var = solve(used_components, 'component', ['total_qty'])

then I try to print my_var in the template as explained above.

edit2:

this is my actual views.py:

def solve(dataset, group_by_key, sum_value_keys):
    dic = defaultdict(Counter)
    for item in dataset:
        key = item[group_by_key]
        vals = {k: item[k] for k in sum_value_keys}
        dic[key].update(vals)
    return dic

def components_by_season(request, season_name):
    season = get_object_or_404(Season, name=season_name)

    orderitems = OrderItem.objects.filter(order__season__name=season_name)

    # variant_ids = OrderItem.objects.filter(order__season__name=season_name).values_list('variant_id', flat=True)
    # components = Component.objects.filter(bom__variant__id__in=variant_ids)

    used_components = []

    for item in orderitems:
        variant_ordered_qty = item.qty
        components = Component.objects.filter(boms__variant__id__exact=item.variant.id)
        for component in components:
            bom_qty = component.boms.get(component=component).qty
            total_qty = bom_qty * variant_ordered_qty
            used_components.append({
                'component': component.name.encode('ascii', 'ignore'),
                'total_qty': total_qty
            })

    out = solve(used_components, 'component', ['total_qty'])

    # counter = Counter(used_components)

    context = {'season': season, 'orderitems': orderitems, 'used_components': used_components, 'out': out}
    return render(request, 'components_by_season.html', context)
davideghz
  • 3,596
  • 5
  • 26
  • 50

3 Answers3

4

Assuming this is actually your real code, my_var is a dict, not a list. Iterating over a dict just gives you the keys; if you want the values as well, you should iterate over .items(). So:

<ul>
    {% for k, v in my_var.items %}
        <li>{{ k }}: {{ v.total_qty }}</li>
    {% endfor %}
</ul>

Note also, there is no product key; the name of the product is just the key in the outer dict.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Hi, it is my real code, just changed some var names just to generalize it; now I added a bit of context to my Q. I tried your code but it does not print anything to the page – davideghz Mar 26 '17 at 16:18
  • That hasn't really helped. Can you show this in context in the view? – Daniel Roseman Mar 26 '17 at 16:19
3

Finally I got it working by passing out.items() to the template and iterating over out, so:

views.py

context = {'out': out.items()}
return render(request, 'components_by_season.html', context)

in my temmplate:

{% for k,v in out %}
    <p>{{ k }}: {{ v.total_qty }}</p>
{% endfor %}
davideghz
  • 3,596
  • 5
  • 26
  • 50
  • Thanks. Worked for me. I was wondering what's the best way to debug this? How to find out that template expects a dict value in the form of `context = {'out': out.items()}` – Prasannjeet Singh Jul 14 '22 at 15:52
2

If you just want to print this to debug, you can use the pprint filter:

{{out|pprint}}
Preston
  • 7,399
  • 8
  • 54
  • 84