0

in my view

   context ={
        "items":Items.objects.all(),
        "item_pics":Item_pics.objects.all(),
    }
    return render(request, 'menu/items.html', context)

my object "item_pics" looks like that

item_pics = [[{'item_id': 1, 'is_front': False, 'url': 'url_to_the_image1'},
             {'item_id': 1, 'is_front': False, 'url': 'url_to_the_image2'},
             {'item_id': 1, 'is_front': False, 'url': 'url_to_the_image3'},
             {'item_id': 1, 'is_front': False, 'url': 'url_to_the_image4'},
             {'item_id': 1, 'is_front': True, 'url': 'url_to_the_image5'},
             {'item_id': 1, 'is_front': True, 'url': 'url_to_the_image6'},
             {'item_id': 1, 'is_front': True, 'url': 'url_to_the_image7'},
             {'item_id': 1, 'is_front': True, 'url': 'url_to_the_image8'},
             {'item_id': 1, 'is_front': True, 'url': 'url_to_the_image9'}],
             [{'item_id': 2, 'is_front': False, 'url': 'url_to_the_image1'},
             {'item_id': 2, 'is_front': False, 'url': 'url_to_the_image2'},
             {'item_id': 2, 'is_front': False, 'url': 'url_to_the_image3'},
             {'item_id': 2, 'is_front': False, 'url': 'url_to_the_image4'},
             {'item_id': 2, 'is_front': False, 'url': 'url_to_the_image5'},
             {'item_id': 2, 'is_front': False, 'url': 'url_to_the_image6'},
             {'item_id': 2, 'is_front': False, 'url': 'url_to_the_image7'},
             {'item_id': 2, 'is_front': False, 'url': 'url_to_the_image8'},
             {'item_id': 2, 'is_front': False, 'url': 'url_to_the_image9'}]
             ]

my template

        {% for pic in item_pics %}
           {% if pic.is_front %}
               <img src="{{ pic.url }}"> 
           {% endif %}
        {% endfor %}

The problem

How can pick the first occurrance of pic.is_front == True and then stop the for loop

Another problem

If pic.is_fron = False for every picture of the item_pics i would like to pick the first pic of the item_pics

in python will be something like

for pics in item_pics:
    found = False
    for pic in pics:
        if pic['is_front'] == True and found == False:
            print(pic['item_id'], pic['url'])
            found = True
    if found == False:
        print(pics[0]['item_id'], pics[0]['url'])
ThunderHorn
  • 1,975
  • 1
  • 20
  • 42

1 Answers1

3

This would be better done in python code - either in the view itself or, if not possible, using a custom template filter.

In the view

item_pics = [{'item_id': 1, 'is_front': False, 'url': 'url_to_the_image'},
         {'item_id': 1, 'is_front': False, 'url': 'url_to_the_image'},
         {'item_id': 1, 'is_front': False, 'url': 'url_to_the_image'}
         {'item_id': 1, 'is_front': False, 'url': 'url_to_the_image'}
         {'item_id': 1, 'is_front': True, 'url': 'url_to_the_image'}
         {'item_id': 1, 'is_front': True, 'url': 'url_to_the_image'}
         {'item_id': 1, 'is_front': True, 'url': 'url_to_the_image'}
         {'item_id': 1, 'is_front': True, 'url': 'url_to_the_image'}
         {'item_id': 1, 'is_front': True, 'url': 'url_to_the_image'}
         ]
 front_pic = None
 for pic in item_pics:
     if pic["is_front"]:
         front_pic = pic
         break
 else:
     front_pic = item_pics[0]
 context = {"item_pics": item_pics, "front_pic": front_pic}
 return render(....)

then in your template you don't have anything else to do than directly use front_pic.

using a custom filter (cf the link to the doc for where to put this code):

@register.filter
def get_front_pic(item_pics):
     for pic in item_pics:
         if pic["is_front"]:
             return pic
     return item_pics[0]

in your template:

{% load front_pic from yourtaglib %}

{% with item_pics|get_front_pic as front_pic %}
<img src="{{ front_pic.url }}">
{% endwith %}
bruno desthuilliers
  • 75,974
  • 6
  • 88
  • 118
  • 1
    @KostadinSlavov as a general rule if there's no simple and obvious way to do it directly in the template then it belongs to python code, and if you cannot do it in the view (because you don't own it) or don't want to do it in the view (because you consider it's really a presentation-only feature and not the view's responsability) then custom tags and filters are your friends. – bruno desthuilliers Aug 22 '18 at 11:44
  • OMG... Facepalm `context{"pics":item_pics.objects.all().order_by('is_front')` then in the template pick the first one and that's all – ThunderHorn Aug 22 '18 at 11:47
  • That's another solution indeed but since you defined item_pics as a list of dicts no one could give you this answer. – bruno desthuilliers Aug 22 '18 at 11:49
  • I am sorry bad explanation my bad.. :( Really thankful for your answer @bruno appreciate the time you spent for writing that amazing answer :) Thank you – ThunderHorn Aug 22 '18 at 11:51
  • Oh and yes, you don' need `.all()` here, you can just `item_pics.objects.order_by(...)` (idem for anything that returns a QuerySet - `.filter()`, `exclude()` etc). `.all()` is only useful when you have no other conditions about the QuerySet. – bruno desthuilliers Aug 22 '18 at 11:51
  • Noted Thank You! – ThunderHorn Aug 22 '18 at 11:52
  • 1
    @KostadinSlavov don't be sorry, it only took me a couple minutes and can be useful for someone else (which is the whole point of SO). – bruno desthuilliers Aug 22 '18 at 11:52