Reputation: 285
So I have a site where users can upload pictures attached to events which will then be shown in an instagram-type layout on the event page. Because of the way my page is designed, though, I can't just iterate the list. I have to call on each object individually (because I am putting them in various spots all over the page, not just in a simple list). Indexing has worked okay for this, but if I try to open an event which has less than the index amount, I get an error. Is there any way to avoid this? Or does anyone have an alternative solution? I need to be able to call on each item in a list individually so that I can individually format where it is and where it links to.
views.py:
def event_detail(request, slug):
Event = Event.objects.get(slug=slug)
image1 = Image.objects.filter(event__slug=slug)[0]
image2 = Image.objects.filter(event__slug=slug)[1]
image3 = Image.objects.filter(event__slug=slug)[2]
return render(request, 'events/event_detail.html', {
'event': event,
'image1': image1,
'image2': image2,
'image3': image3,
})
Then I call on the objects with {{ image1.url }} etc.
Right now it's set up to support 3 (or more) images, but if the event has less than 3 images attached, I get the error.
Very much open to alternative ways to model this as well, if anyone has ideas.
Upvotes: 0
Views: 196
Reputation: 1131
You can send the Images and events to html page as @karthikr mentioned
def event_detail(request, slug):
Event = Event.objects.get(slug=slug)
images = Image.objects.filter(event__slug=slug)[:3]
return render(request, 'events/event_detail.html', {
'event': event,
'images': images})
and then in html pages you can call the images by indexing If you want to call it individually by doing.
{{ images.0.url }}
{{ images.1.url }}
Its using indexing in Templates. If you are sure there would be specified number of images on the template
Upvotes: 1
Reputation: 99640
The issue occurs because you are evaluating the queryset by indexing. So it would naturally fail if the queryset does not have 3 images.
One thing you could do is, handle it slightly differently:
def event_detail(request, slug):
Event = Event.objects.get(slug=slug)
images = Image.objects.filter(event__slug=slug)[:3]
return render(request, 'events/event_detail.html', {
'event': event,
'images': images
})
Now you could do :
{% for image in images %}
{% image.url %}
{% endfor %}
This way, [:3]
would slice the queryset "safely", and the template would only render the objects that are present in the images
queryset
Edit:
To accommodate the sets of 2 your are looking for, another thing you could do is:
def event_detail(request, slug):
Event = Event.objects.get(slug=slug)
image_set_1 = Image.objects.filter(event__slug=slug)[:2]
image_set_2 = Image.objects.filter(event__slug=slug)[2:4]
image_set_3 = Image.objects.filter(event__slug=slug)[4:6]
return render(request, 'events/event_detail.html', {
'event': event,
'image_set_1': image_set_1,
'image_set_2': image_set_2,
'image_set_3': image_set_3,
})
Now this slice is "safe", so you can render it wherever you want.
Upvotes: 3