Amit Pal
Amit Pal

Reputation: 11042

How to access a list and dictionary in same for loop at template level in Django

I have a function in view.py which returns two variables i.e. a dictionary named ca and a list named categories:

def eventcateg_detail(request):
    ca = EventTypeCategory.objects.values()
    categories =[]
    for i in range(0, len(ca)):
       pk_sub = ca[i]['sub_categ_id']
       if (pk_sub!=None):
          category = EventTypeCategory.objects.get(id = pk_sub)
          category = category.name
          categories.append(category)
    return render(request,"events/categ.html",{
      'obj': ca,
      'categ' :categories
      })

categ returns:

[u'Critical in list', u'Information in list', u'Amit Pal in list']

My categ.html is:

<thead>
        <tr><th>{% trans "Name Category" %}</th><th>{% trans " Message" %}</th><th>{% trans "Sub-categories" %}</th></tr>
    </thead>
    <tbody>
    {% for obj in obj %}
        <tr>

            <td>{{ obj.name }}</td><td> {{ obj.Message_slug }}</td><td></td>

        </tr>
    {% endfor %}
    </tbody>
</table>

My output should be:

Event Category  Event Message   Sub-categories
Critical            critical    critical in list
Information         information information in list
Amit Pal            amit-pal    amit pal in list

Sub categories contain the data coming from the list. I am getting Event Category (using obj.name) and Event Message (using obj.Message_slug) right but I'm not able to find any way to put sub-categories also in the same td and the same for loop (look at the template).

Upvotes: 0

Views: 327

Answers (1)

Mikael
Mikael

Reputation: 3236

I would suggest that you look at this: Django, category and subcategories

This will probably require some changes to your model but will simplify your code a lot.

UPDATE

I will answer your first question then :)

You can nest for loops so in your case:

<thead>
    <tr><th>{% trans "Name Category" %}</th><th>{% trans " Message" %}</th><th>{% trans "Sub-categories" %}</th></tr>
</thead>
<tbody>
{% for obj in obj %}
    <tr>

        <td>{{ obj.name }}</td><td> {{ obj.Message_slug }}</td>
        <td>
            {% for i in categ %}
                  {{ i }}
            {% endfor %}
        </td>

    </tr>
{% endfor %}
</tbody>

However! The above code points to a weakness in your eventcateg_detail method. The list that you create does not tell which parent-category the list item belongs to so for each parent object all items will be printed.

If you know that there will always be a one-to-one relationship and there will always be one child only you can create a dictionary instead

Also, I believe that your initial code can be simplified:

def eventcateg_detail(request):
        ca = EventTypeCategory.objects.all()
        categories ={}
        for cat in ca:
            if cat.sub_categ_id:

               #Since the ca queryset already contains all items you can use that to get the child category
               category = ca.objects.get(id=cat.sub_categ_id)

               #Add to dictionary. NOTE: If you ever get more than one sub-category 
               #you need to build a list of sub-categories before adding it to the dict.
               categories[cat.id] = category.name
        return render(request,"events/categ.html",{ 'obj': ca, 'categ' :categories})

In your template you do this:

<thead>
<tr>
     <th>{% trans "Name Category" %}</th>
     <th>{% trans " Message" %}</th><th>{% trans "Sub-categories" %}</th>
</tr>
</thead>
<tbody>
{% for o in obj %}
<tr>
    <td>{{ o.name }}</td><td> {{ o.Message_slug }}</td>
    <td>
        {% for key, value in categ.items %}
              {% ifequal key o.id %}
               {{ value }}
              {% endifequal %}
        {% endfor %}
    </td>

</tr>

{% endfor %}

Upvotes: 2

Related Questions