Pierre Aim
Pierre Aim

Reputation: 3

Double loop for in template

I've actually a problem with my template and my loops. I have the same problem described here : Double loop in Django template I have tryed the answer but it doesn't work :/ And I don't understand the django documentation about backward relationship

I've tryed to prefetch_related and selected_related like in the link above and other search about my problem but I don't really understand what does it do.

Models :

class Categories(models.Model):
    name = models.CharField(max_length=255)
    def __str__(self):
        return self.name

class SousCategories(models.Model): #subcategories
    name = models.CharField(max_length=255)
    categorie = models.ForeignKey(Categories, on_delete=models.CASCADE, null=True)
    def __str__(self):
        return self.categorie.name + " " + self.name

View :

def index(request):
    response_dict = dict()
    lst_cat = []
    lst_ss_cat = []
    for cat in Categories.objects.all():
        all_cat = dict()
        all_cat['id'] = cat.id
        all_cat['name'] = cat.name
        lst_cat.append(all_cat)
    for ss_cat in SousCategories.objects.all():
        all_ss_cat = dict()
        all_ss_cat['id'] = ss_cat.id
        all_ss_cat['name'] = ss_cat.name
        all_ss_cat['cat'] = ss_cat.categorie
        lst_ss_cat.append(all_ss_cat)
    response_dict['categorie'] = lst_cat
    response_dict['ss_cat'] = lst_ss_cat
    print(response_dict)
    return render(request, "home.html", {'cat': response_dict})

This view give me this (Few datas just for test) :

{'categorie': [{'id': 1, 'name': 'playmobil'}, {'id': 2, 'name': 'deguisements'}], 'ss_cat': [{'id': 1, 'name': 'neuf', 'cat': <Categories: playmobil>}, {'id': 2, 'name': 'occasion', 'cat': <Categories: playmobil>}, {'id': 3, 'name': 'propre', 'cat': <Categories: deguisements>}, {'id': 4, 'name': 'sale', 'cat': <Categories: deguisements>}]}

Template :

<div class="wrapper">
 <nav id="sidebar">
   <div class="sidebar-header">
     <img src="{% static "logo.png" %}" alt="My image">
   </div>
   <ul class="list-unstyled components">
     <p>Categories</p>
     {% for categ in cat.categorie %}
     <li>
       <a href="#{{categ.name}}" data-toggle="collapse" aria-expanded="false" class="dropdown-toggle">{{categ.name|capfirst}}</a>
       <ul class="collapse list-unstyled" id="{{categ.name}}">
         {% for ssc in cat.ss_cat %}
         <li>
           <a href="#">{{ssc.name}}</a>
         </li>
         {% endfor %}
       </ul>
     </li>
     {% endfor %}
   </ul>
 </nav>
 </div>

The actual result is that my ul balise is empty instead of containing my subcategories. Then if someone can explain me how backward relationship works or have the solution for my problem (I've found this doc but i'm lost : https://docs.djangoproject.com/en/dev/topics/db/queries/#following-relationships-backward) PS : I use the last version of python and django

Upvotes: 0

Views: 60

Answers (2)

Kyryl Havrylenko
Kyryl Havrylenko

Reputation: 694

You can access SousCategories in Category instance via category.souscategories_set.all(), no need to iterate over things in the view.

Upvotes: 0

dirkgroten
dirkgroten

Reputation: 20702

See my comments inline explaining what's happening with your code:

     {% for cat in cat.categorie %}
         <!-- here cat is redefined as {'id': 1, 'name': 'playmobil'} the first loop -->
     <li>
       ...
       <ul>
         {% for ssc in cat.ss_cat %}
              <!-- cat.ss_cat doesn't exist: no key `ss_cat` (only 'id' or 'name') -->
              ...
         {% endfor %}
       </ul>
     </li>
     {% endfor %}

but as explained by the other comments and answers, even if you name the loop variable differently, you would still loop through all the sub categories each time, unrelated to the main category, so it wouldn't do what you want.

Upvotes: 1

Related Questions