Home > database >  Django. Access list index in child for loop
Django. Access list index in child for loop

Time:01-08

How can I change the accessed index of an inner for loop list based on a counter from the outer loop? In normal python I would do something like

parent_list = ['One','Two','Three']
child_list = ['A','B','C']

for idx, item in enumerate(parent_list):
    for child_item in child_list[idx]:
        print(str(idx), item, child_item)

I've been looking at using with and forloop.counters but I either run into the index not being accessed or index not changing. This is what I currently have.

    {% for item in payout_items %}
        {% with forloop.counter0 as outer_counter %}
        <h2>{{ item.market_place }} on {{ item.entry_date }}:
            {% for item in royalty_items.outer_counter %}
                <tr>
                <th scope="row">{{ item.id }}</th>
                <td>{{ item.entry_date }}</td>
                <td>{{ item.market_place }}</td>
                </tr>
            {% endfor %}
        {% endwith %}
    {% endfor %}

If I change

{% for item in royalty_items.outer_counter %}

to

{% for item in royalty_items.0 %}

I get the first index repeated many times. I can see that outer_counter is incrementing from the output but just need royalty_items to increment the accessed index as well.

As requested the view is

    detail_object = AccountingPeriod.objects.get(pk=detail_id)
    payout_items = Payout.objects.filter(sales_period_start__range=[detail_object.period_start, detail_object.period_end])

    royalty_items = []
    for payout in payout_items:
        temp = Royalty.objects.filter(entry_date__range=[payout.sales_period_start, payout.sales_period_end]).filter(market_place=payout.market_place)
        print(str(payout.sales_period_start)   " - "   str(payout.sales_period_end)   " - "   payout.market_place   " = "   str(len(temp)))
        royalty_items.append(temp)

And the following render call is passed.

render(request, 'royalties/accounting_period/summary.html', {'detail_object': detail_object, 'payout_items': payout_items, 'royalty_items': royalty_items})

Solution: I created a template filter but feel there should be a more elegant answer.

@register.filter()
def getRoyaltySet(royalty_items, outer_counter):
    return royalty_items[outer_counter]

CodePudding user response:

I would just add this to the items, so:

detail_object = get_object_or_404(AccountingPeriod, pk=detail_id)
payout_items = Payout.objects.filter(
    sales_period_start__range=(
        detail_object.period_start,
        detail_object.period_end,
    )
)
for payout in payout_items:
    temp = Royalty.objects.filter(
        entry_date__range=(payout.sales_period_start, payout.sales_period_end),
        market_place=payout.market_place,
    )
    print(
        f'{payout.sales_period_start} - {payout.sales_period_end} - {payout.market_place} = {len(temp)}'
    )
    payout.royalities = temp

Then you can access this through .royalities:

{% for item in payout_items %}
    <h2>{{ item.market_place }} on {{ item.entry_date }}</h2>:
        {% for subitem in item.royalites %}
            <!-- … -->
        {% endfor %}
{% endfor %}

CodePudding user response:

You can use forloop.parentloop to get to the outer forloop

{{ forloop.parentloop.counter }}

You can even chain them if you have nested loops:

{{ forloop.parentloop.parentloop.counter }}

If you wanna absolutely use your own index you can access the dictionary with .items:

{% for key, value in mydict.items %}
    {% for key2, value2 in otherdict.items %}
        <div>{{ key }} - {{ key2 }}</div>
    {% endfor %}
{% endfor %}
  • Related