Felipe Dourado
Felipe Dourado

Reputation: 441

Django | where to iterate: views or template

I'm wondering where is the best place to build the code I need: template or views.

Let's say I have 3 lists and inside some dicts:

sell = [{'date__month': 1, 'date__year': 2020, 'sells_by_month': 15}, {'date__month': 5, 'date__year': 2020, 'sells_by_month': 115}]
payments = [{'date__month': 5, 'date__year': 2020, 'payments_by_month': 18}]
provider = [{'date__month': 4, 'date__year': 2020, 'providers_by_month': 200}, {'date__month': 5, 'date__year': 2020, 'providers_by_month': 320}]

For every month/year I need to check if there is any sells, payments or providers. I need to display in templates something like that

Period  Sells   Payments   Provider 
01-2020 15      0          0     
02-2020 0       0          0
03-2020 0       0          0
04-2020 0       0          200
05-2020 115     18         320
06-2020 0       0          0

I can build another dict with a loop in views.py but anyway I'll need to create another loop to display all this table in templates. So I guess this could take too much time with a desnecessary looping in views.py.

Is it possible to create some code directly in templates with just one if-else loop condition OR it's a good pratice to build the whole dict in views.py?

What do you think?

Upvotes: 1

Views: 271

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 477264

Is it possible to create some code directly in templates with just one if-else loop condition OR it's a good pratice to build the whole dict in views.py?

Possible, maybe yes, but no it is not good practice at all. A template is about rendering data in a pleasant form. A view should handle the business logic. While there is a "gray zone", usually from the moment in involves function calls, arbitrary dictionary lookups, etc. you better do this in a view. In fact Django's template language is deliberately restricted to discourage doing these things in a view.

We can make a list of dictionaries with the data with:

def records_to_dict(records, key):
    return {(r['date__year'], r['date__month']): r[key] for r in records}

dict_sell = records_to_dict(sell, 'sells_by_month')
dict_payments = records_to_dict(payments, 'payments_by_month')
dict_provider = records_to_dict(provider, 'providers_by_month')

Next we can summarize this, for example by looping over the months:

half_year = [
    {'year': y, 'month': m, 'sells': dict_sell.get((y, m), 0), 'payments': dict_payments.get((y, m), 0), 'providers': dict_provider.get((y, m), 0)}
    for y in range(2020, 2021)
    for m in range(1, 7)
]

Now half_year will contain data that looks like:

[{'month': 1, 'payments': 0, 'providers': 0, 'sells': 15, 'year': 2020},
 {'month': 2, 'payments': 0, 'providers': 0, 'sells': 0, 'year': 2020},
 {'month': 3, 'payments': 0, 'providers': 0, 'sells': 0, 'year': 2020},
 {'month': 4, 'payments': 0, 'providers': 200, 'sells': 0, 'year': 2020},
 {'month': 5, 'payments': 18, 'providers': 320, 'sells': 115, 'year': 2020},
 {'month': 6, 'payments': 0, 'providers': 0, 'sells': 0, 'year': 2020}]

Now you can render this in a template, for example:

<table>
{% for item in half_year %}
    <tr>
        <td>{{ item.year }}-{{ item.month }}</td>
        <td>{{ item.sells }}</td>
        <td>{{ item.payments }}</td>
        <td>{{ item.providers }}</td>
    </tr>
{% endfor %}
</table>

Upvotes: 3

Related Questions