user9305920
user9305920

Reputation:

Django display table in templates

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

Answers (5)

Borut
Borut

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

iklinac
iklinac

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

Ben
Ben

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

unixia
unixia

Reputation: 4350

A few things,

  1. Since your model name is already Category, your field names should be like name instead of category_name.
  2. Model names must be singular, so it should beCategoryItem instead of CategoryItems
  3. When you do a 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

Bruno Lucena
Bruno Lucena

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

Related Questions