30

This is hopefully a quick/easy one. I know a way to work around this via a custom template tag, but I was curious if there were other methods I was over looking. I've created a gallery function of sorts for my blog, and I have a gallery list page that paginates all my galleries. Now, I don't want to show all the photos of each gallery in that list, since if each gallery even has 20 images, then that's 100 images on a page if I paginate at 5 posts. That'd be wasteful, and the wrong way to go about things.

The question I have is, is there a way to just display 3 photos from the photo set? What I'd like to do, but I don't think is possible is something like (pseudocode):

{% for photos in gallery.photo_set %}
   {% if forloop.counter lt 3 %}
     <img src="{{ photos.url }}">
   {% endif %}
{% endfor %}

Judging from the documentation, unless I'm completely missing it, that's not possible via the templating system. Hence, I can just write my own template tag of sorts to work around it. I could probably do something from the view aspect, but I haven't looked to far into that idea. The other option I have is giving the model a preview field, and allow the user to select the photos they want in the preview field.

Anyways, a few different options, so I thought I'd poll the audience to see how you'd do it. Any opinion is appreciated. Personally, enjoying that there's numerous ways to skin this cat.

AnthonyWJones
  • 187,081
  • 35
  • 232
  • 306
f4nt
  • 2,661
  • 5
  • 31
  • 35

2 Answers2

86

Use:

{% for photos in gallery.photo_set|slice:":3" %}
Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
  • 2
    So, there's all my options, and then there's your blatantly obvious one that I've been overlooking. Thanks for the tip, saves me a ton of trouble! – f4nt Jun 14 '09 at 07:52
  • 5
    Using the slice filter has an additional benefit. If you're passing in a Django QuerySet (as opposed to a collection), the slice will flow through to the underlying SQL query, limiting the number of rows that the page will actuall retrieve from the database. – Dave W. Smith Jun 14 '09 at 17:44
  • @Dave, +1: thanks, I didn't know about that optimization -- cool! – Alex Martelli Jun 14 '09 at 18:47
1

This is better done in the gallery.photo_set collection. The hard-coded "3" in the template is a bad idea in the long run.

class Gallery( object ):
   def photo_subset( self ):
       return Photo.objects.filter( gallery_id = self.id )[:3]

In your view function, you can do things like pick 3 random photos, or the 3 most recent photos.

   def photo_recent( self ):
       return Photo.objects.filter( gallery_id = self.id ).orderby( someDate )[:3]

   def photo_random( self ):
       pix = Photo.objects.filter( gallery_id = self.id ).all()
       random.shuffle(pix)
       return pix[:3]
S.Lott
  • 384,516
  • 81
  • 508
  • 779
  • 1
    Actually, since the 3 has to do with the presentation it fits in the template, other templates might have more space and want to present 4 photos, no? – noio Mar 23 '11 at 10:24
  • @Noio: Grouping the photos into lists of lists should be in the view function. The template just takes the lists of lists and displays them. – S.Lott Mar 23 '11 at 10:56
  • 2
    lott it's odd that you're telling him not to "hard code" a constant in the template, but then providing an example of that same constant in the server code. This is terrible advice - the template is exactly where you'd want to put a variable that may changed based on design changes. – Will Curran Apr 16 '11 at 00:29
  • @Will Merydith: Sorry. I disagree. In my experience, the templates can (and should) be generic and the view functions can include weird constants. Constants that often come from the settings file. – S.Lott Apr 16 '11 at 01:09
  • 3
    Have to agree with the others here. The template is the place for this. If you're worried about duplication, create the bit of HTML as an include, but the design is usually dependent on things like this. Say the design literally only has room for 3. The template will usually make it clear that you can't fit more, while the view is more abstract. If someone comes by later and decides to change the view to show 5, it might then break the template. – Chris Pratt Jun 28 '11 at 14:25