Vitaly
Vitaly

Reputation: 2585

ForeignKey and Django Template

So here's the problem. Imagine 2 models: Photographer and Photo. Strict rule is that there can be only 1 photographer for image, so in Photo there's a ForeignKey link to Photographer.


class Photographer(models.Model):
    name = models.CharField(max_length = 40)

class Photo(models.Model):
    name = models.CharField(max_length = 40)
    photographer = models.ForeignKey(Photographer)

Now I'd like to show most famous photographers on a main page with 3 most popular his photos. So it should be something like:


# views.py
def main(request):
    photographers = ...
    return render_to_response("main_page.html", {
                "photographers": photographers
           })

#main_page.html
{% for photo in photographers.photo_set.all()[:3] %}
{{ photo.name }}
{% endfor %}

But Django templating system doesn't allow all() and [:3]. So what is the best way to do that? The most obvious solution would be to create objects on the fly (create array from photographers and photos and pass it to template), but I just don't see this a good way.

Please don't just refer me to Django manual, I read it thoroughly, but couldn't find an answer...

Upvotes: 4

Views: 3684

Answers (3)

Vinay Sajip
Vinay Sajip

Reputation: 99485

I think Yuval A's almost got it, but not quite - the photos and photographers seem to be mixed up. I think the best approach would be to provide a top_photos attribute on the Photographer model which returns the top 3 (or however many) photos. Then:

{% for photographer in photographers %}
Photographer: {% photographer.name %}
Top Photos:
{% for photo in photographer.top_photos %}
{% photo.name}
{% endfor %}
{% endfor %}

I've left out any HTML formatting in the above, but hopefully the intent is clear.

Upvotes: 2

Jeff Bradberry
Jeff Bradberry

Reputation: 1607

Try using the slice filter:

{% for photo in photographers.photo_set.all|slice:":3" %}

Note that the .all doesn't need to be explicitly called.

Upvotes: 6

Yuval Adam
Yuval Adam

Reputation: 165312

You got it, you just need to move the logic to the view, and just pass the template the objects once you've got them.

# views.py
def main(request):
    photographers = photographers.photo_set.all()[:3]
    return render_to_response("main_page.html", {
                "photographers": photographers
           })

#main_page.html
{% for photo in photographers %}
{{ photo.name }}
{% endfor %}

Make sure your views contain the logic and the template just shows the data.

Upvotes: 1

Related Questions