Django суммирование значений из цикла for в шаблоне
Я хочу вывести сумму значений (калорий, белков, углеводов и т. д.) нескольких продуктов в новой таблице, но не представляю, как это сделать в шаблоне django.
Здесь показано, что отображает цикл for
{% for food in meal.foods.all %}
<div class='table-container'>
<table class='food-table'>
<thead>
<tr>
<th>Name</th>
<th>Calories</th>
<th>Protein</th>
<th>Carbs</th>
<th>Fat</th>
<th>Sugar</th>
<th>Sodium</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ food.name }}</td>
<td>{{ food.calories }}</td>
<td>{{ food.protein }}g</td>
<td>{{ food.carbs }}g</td>
<td>{{ food.fat }}g</td>
<td>{{ food.sugar }}g</td>
<td>{{ food.sodium }}mg</td>
</tr>
</tbody>
</table>
</div>
{% endfor %}
Новая таблица будет выглядеть следующим образом, но в ней будут отображаться только итоговые значения.
Это можно сделать, используя функцию SUM()
в SQL через функцию aggregate Sum. Пример использования здесь.
>>> from django.db.models import Sum
>>> from my_app.models import Food, Meal
>>>
>>> Food.objects.values()
<QuerySet [{'id': 1, 'name': 'Fries', 'calories': Decimal('150.00'), 'protein': Decimal('10.00')}, {'id': 2, 'name': 'Burger', 'calories': Decimal('200.00'), 'protein': Decimal('13.00')}, {'id': 3, 'name': 'Celery', 'calories': Decimal('30.00'), 'protein': Decimal('9.00')}, {'id': 4, 'name': 'Coke', 'calories': Decimal('500.00'), 'protein': Decimal('22.00')}]>
>>>
>>> meal = Meal.objects.get(name='Snack')
>>> meal.foods.values()
<QuerySet [{'id': 1, 'name': 'Fries', 'calories': Decimal('150.00'), 'protein': Decimal('10.00')}, {'id': 2, 'name': 'Burger', 'calories': Decimal('200.00'), 'protein': Decimal('13.00')}, {'id': 4, 'name': 'Coke', 'calories': Decimal('500.00'), 'protein': Decimal('22.00')}]>
>>>
>>> meal.foods.aggregate(Sum('calories'), Sum('protein'))
{'calories__sum': Decimal('850'), 'protein__sum': Decimal('45')}
Затем вы можете просто передать результат dict в ваш шаблон для просмотра.
Если с едой произойдут изменения, это отразится на звонке aggregate
.
>>> Food.objects.create(name='Chips', calories=80, protein=5)
<Food: Food object (5)>
>>> meal.foods.add(Food.objects.get(name='Chips'))
>>> meal.foods.aggregate(Sum('calories'), Sum('protein'))
{'calories__sum': Decimal('930'), 'protein__sum': Decimal('50')}
Как я понимаю, вы хотите получить общее количество протеинов, крабов, ... из конкретного блюда.
Простым способом достижения этого было бы создание новых property
в моделях Meal
.
class Meal(models.Model):
...
@property
def get_total_protein(self):
return sum([food.protien for food in self.foods.all()])
@property
def get_total_carbs(self):
return sum([food.carbs for food in self.foods.all()])
# and the same for fat, sugr..
затем вы можете получить доступ к ним в вашем шаблоне. например, давайте обратимся к ним в table foot
<tfoot>
<tr>
<th></th>
<th></th>
<th>{{ meal.get_total_proteins }}</th>
<th>{{ meal.get_total_carbs }}</th>
<th> ... </th>
<th> ... </th>
<th> ... </th>
</tr>
</tfoot>