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;
{{ zipped|length }}
{% for u, y in zipped %}
{{ u }}---{{ y.title }}
{% endfor %}
len gives 0, and loop is empty. What's the reason of it?
CodePudding user response:
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.