Reputation:
I am using Django 2.0.1, and I have the following code:
Models.py:
class Category(models.Model):
category_name = models.CharField(max_length=50)
class CategoryItems(models.Model):
category_name = = models.ForeignKey(Categories, related_name='categoriesfk', on_delete=models.PROTECT)
item_name = models.CharField(max_length=50)
item_description = models.CharField(max_length=100)
Thereafter my views.py:
def data(request):
categories_query = Categories.objects.all()
category_items_query = CategoriesItems.objects.all()
return render_to_response("data.html",
{'categories_query': categories_query,'category_items_query': category_items_query}
In the template I'm trying to display all items for each category, for example, suppose there are 4 categorizes, e.g. Bicycle, then it display all items belonging to that category only. For example, as follows:
Category 1:
Category_Item 1,
Category_Item 2,
Category_Item 3,
and so on ...
Category 2:
Category_Item 1,
Category_Item 2,
Category_Item 3,
and so on ...
I have tried to write so many different for-loops, but they just display all items, I need it to show items only for that category, then for loop to next category and show items for that.
Upvotes: 0
Views: 3621
Reputation: 3364
Django has a built-in regroup
template tag for this functionality.
{% regroup category_items_query by category_name as categoryname_list %}
{% for category in categoryname_list %}
<strong>{{ category.grouper }}</strong><br>
{% for item in category.list %}
{{ item.item_name }}: {{ item.item_description }}<br>
{% endfor %}
{% endfor %}
You have to order your CategoryItems for this functionality to work.
category_items_query = CategoriesItems.objects.all().order_by('category_name')
Upvotes: 0
Reputation: 15758
Grouping data in template is not best idea as template should be logic free, also good idea would be to use database capabilities and use select_related to query out related set
category_data = Category.objects.select_related('item').all()
afterwards you could do following in template
{% for category in category_data %}
{# print category #}
{% for item in category.items %}
{# print item #}
{% endfor %}
{% endfor %}
Upvotes: 0
Reputation: 6777
You don't need your category_items_query
variable, just category_query
:
{% for category in category_query %}
<b>{{ category.category_name }}</b><br />
{% for item in category.categoriesfk.all %}
{{ item.item_name }}<br />
{% endfor %}
{% endfor %}
Your related_name
of categoriesfk
is weird, it'd make more sense to be something like items
.
Upvotes: 1
Reputation: 4350
A few things,
name
instead of category_name
.CategoryItem
instead of CategoryItems
model_name.objects.all()
, you do not get a query but a Queryset
, make your variable names such that they describe what they do. Currently, categories_query
is wrong. You could instead use category_qs
.Now, coming to your question, you require two for loops. One to loop through the categories and then one to loop through items in a particular category.
Something like,
for category in category_qs:
for item in category:
# Do something with item
You have the basic idea here, now you can convert it to real working code. Good luck!
Upvotes: 0
Reputation: 484
What you need is two for loops with an if to check if the second loop should belong to the first. Try this:
{% for category in categories_query %}
{% for category_item in category_items_query %}
{% if category_item.category_name == category %}
{# do something with category_item #}
{% endif %}
{% endfor %}
{% endfor %}
I believe it would be more clear if you named the ForeignKey in CategoryItems to just "category", instead of "category_name", since this field will have the category itself, not just it's name. Your "if" would then be more readable and make more sense:
{% if category_item.category == category %}
Hope it helps.
Upvotes: 0