Total and subtotal in django template using lists

2

How do I calculate the subtotal and total per store (store) in the view to play the results in the template? In case I'm using lists.

def quotation_list(request):
    stores = list(Store.objects.all())
    products = list(Product.objects.all())
    # indice
    index_store = {store.id: index for index, store in enumerate(stores)}
    index_product = {product.id: index for index,
                     product in enumerate(products)}
    # dados para o template
    cabecalho = ["Lojas"] + [store.store for store in stores]
    linhas = [([product.product] + [None for store in stores])
              for product in products]

    for pev in Quotation.objects.all():
        total = pev.price * pev.quantity
        linhas[index_product[pev.product_id]][index_store[pev.store_id] +
                                              1] = (pev.price, pev.quantity, total, pev.store, pev.product)

    # retorna o menor preço de cada produto
    # a quantidade, total e loja também estão nesta lista
    mais_barato = []
    for linha in linhas:
        mais_barato.append(min(linha[1:]))

    # destaca os menores preços no template
    mb = 0
    if request.GET.get('mais_barato', False):
        mb = 1

    # mostra somente os menores preços
    smb = 0
    if request.GET.get('somente_mais_barato', False):
        smb = 1

Notice that here I order the list by store.

    # mostra os produtos mais baratos, a quantidade e o total
    bqt = 0
    if request.GET.get('quantidade_e_total', False):
        mais_barato = sorted(mais_barato,
                             key=lambda store: str(store[3]))  # sort by store
        bqt = 1

    context = {
        'cabecalho': cabecalho,
        'linhas_mais_barato': zip(linhas, mais_barato),
        'mb': mb,
        'smb': smb,
        'bqt': bqt,
    }
    return render(request, 'core/quotation_list.html', context)

I've tried something similar to this here

link

But it did not work.

    
asked by anonymous 06.12.2015 / 07:31

1 answer

2

I do not understand if the subtotal refers to the rows, columns, or both, so I'll respond to "both" (although in your particular case this does not make sense).

To calculate the subtotal of the row, add one more element in each row. To calculate the subtotal of the column, add one more line. During the fill (when you iterate over the relationship table), you will update the values of the subtotals in either case:

cabecalho = ["Lojas"] + [store.store for store in stores] + ["Subtotal"]
linhas= [([product.product] + [None for store in stores] + [(0,0,0,None,product.product)])
            for product in products
        ] +
        [["Subtotal"] + [(0,0,0,store.store,None) for store in stores] + [(0,0,0,None,None)]]

def soma_tuplas(a, b):
    return (a[0]+b[0], a[1]+b[1], a[2]+b[2], a[3], a[4])

for pev in Quotation.objects.all():
    total = pev.price * pev.quantity

    i0 = index_product[pev.product_id]
    i1 = index_store[pev.store_id] + 1
    valor = (pev.price, pev.quantity, total, pev.store, pev.product)

    linhas[i0][i1] = valor

    # Subtotal da linha (se fizer sentido no seu caso)
    linhas[i0][len(stores)+1] = soma_tuplas(linhas[i0][len(stores)+1], valor)

    # Subtotal da coluna (se fizer sentido no seu caso)
    linhas[len(produtos)][i1] = soma_tuplas(linhas[len(produtos)][i1], valor)

    # Total da tabela (se fizer sentido no seu caso)
    linhas[len(produtos)][len(stores)+1] = 
        soma_tuplas(linhas[len(produtos)][len(stores)+1], valor)

If I understand what you are modeling, only the subtotals per column make sense in your case, and the value that will interest you in the end is the sum of the totals (ie sum of the times quantity quantities of all the products of a store) - that is, the index 2 of the tuple. But I gave a complete answer if anyone in the future finds this question useful.

Detail: If you do this, you do not need to touch mais_barato , because it will calculate the minimum of subtotals as well. :)

Addendum: In your previous question I had suggested using zip to join linhas and mais_barato - which is a quick solution for iterating over two lists at once . But if you are ordering one or the other, it is important to keep the elements together, otherwise the values for each line will not match the values of the minimums:

linhas_mais_barato = zip(linhas, mais_barato) # Primeiro faz o zip, depois ordena

# mostra os produtos mais baratos, a quantidade e o total
bqt = 0
if request.GET.get('quantidade_e_total', False):
    linhas_mais_barato = sorted(linhas_mais_barato,
                                key=lambda store: str(store[1][3]))  # sort by store
    bqt = 1

context = {
    'cabecalho': cabecalho,
    'linhas_mais_barato': linhas_mais_barato,

(I do not know if this is right, or if what you wanted was actually sort by column and not by line, but the important thing is to keep linhas and mais_barato consistent) >     

06.12.2015 / 12:19