Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

zipped data shown in view but not in templete

row1 = []
row2 = []

categories= Kategoriler.objects.all().filter(parent_id__isnull=True).order_by('id')
for x in categories:
    row1.append(x.title)
    row2.append(Kategoriler.objects.all().filter(parent_id=x.id).order_by('title'))

zipped = itertools.zip_longest(row1, row2)


for u, y in zipped:
    print(">>>>>>>>>>>>>>>", u, "<<<<<<<<<<<<<<<<<<<<")
    for q in y:
        print(q.title)


context = {'segment': 'categories', "zipped": zipped}

Above code prints as expected in view.py

In templete;

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

{{ zipped|length }}
                {%  for u, y in zipped %}
                    {{ u }}---{{ y.title }}
                {%  endfor %}

len gives 0, and loop is empty.
What’s the reason of it?

>Solution :

You should not enumerate over zip in the view, since that will "consume" the iterator, and then the iterator is thus "exhausted". You pass zipped to the view without enumerating, so:

from itertools import zip_longest

row1 = []
row2 = []
categories = Kategoriler.objects.filter(parent=None).order_by('id')
for x in categories:
    row1.append(x.title)
    row2.append(Kategoriler.objects.filter(parent_id=x.id).order_by('title')

zipped = zip_longest(row1, row2)
# no enumeration
context = {'segment': 'categories', "zipped": zipped}

In the template you can then render with:

{% for u, ys in zipped %}
    {% for y in ys %}
        {{ u }}---{{ y.title }}
    {% endfor %}
{% endfor %}

You should not use {{ zipped|length }} since this will again consume the zipper.

That being said, the zipping is unnecessary and inefficient: it will make N+1 queries if categories contains N elements. You can fetch the items with:

from django.db.models import Prefetch

categories = Kategoriler.objects.filter(
    parent=None
).prefetch_related(
    Prefetch('kategoriler_set', Kategoriler.objects.order_by('title'))
).order_by('id')
context = {'segment': categories}

In the template you can then render this with:

{% for segment in segment %}
    {% for sub in segment.kategoriler_set.all %}
        {{ segment.title }}---{{ sub.title }}
    {% endfor %}
{% endfor %}

If you set a related_name=… [Django-doc] for the ForeignKey named parent, then you should replace kategoriler_set with that value.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading