I have a Ingredient model and a Shopping model for a shopping list and I would like to group ingredients by their category in the shopping list view. Is there a database method to achieve this or will running the for loop I have in my Views.py the easiest?
The below image is exactly what I would like to achieve in my shopping list view:
html:
{% for key, value_list in shoppingList.items %}
<div >{{key}}</div>
{% for value in value_list %}
<div>
<li>{{value}}</li>
</div>
{% endfor %}
{% endfor %}
models.py:
class Ingredient(models.Model):
name = models.CharField(max_length=220)
category = models.CharField(max_length=50, default="uncategorised")
class Shopping(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=220, blank=True, null=True) # users can create their own items not just those in the Ingredient model
category = models.CharField(max_length=80, default="uncategorised")
views.py:
def shopping_list_view(request):
queryset = Shopping.objects.filter(user=request.user)
shoppingList = {}
for item in queryset:
ingredientItem = item.name # e.g Fish
ingredientCategory = item.category # e.g. Meat & Seafood
if ingredientCategory in shoppingList:
shoppingLists[ingredientCategory].append(ingredientItem)
else:
shoppingLists[ingredientCategory] = []
shoppingLists[ingredientCategory].append(ingredientItem)
# print(shoppingLists)
# will return something like > {'Meat & Seafood': ['bacon', 'fish'], 'Baking & Spices': ['all purpose flour', 'parsley'], 'pantry': ['pasta']}
return render(request, "shopping/shoppinglist.html", {"shoppingList": shoppingList}
)
CodePudding user response:
In case you use PostgreSQL, you can use ArrayAgg in annotate with values:
from django.contrib.postgres.aggregates import ArrayAgg
queryset = Shopping.objects.filter(
user=request.user
).values("ingredients__category").annotate(
ingredient_list=ArrayAgg('ingredients__name')
).all()
Then you'll get the list with desired structure and wouldn't need to perform any calculations at Python's side.

