Home > Blockchain >  Group queryset into categories django
Group queryset into categories django

Time:01-20

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 %}

rendered html

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.

  •  Tags:  
  • Related