1
votes

I am trying to build a photo gallery with Django.

It is set up by category.

I have paginated the results of a category by n amount of images per page. I want to also use the paginator on the page that shows just the single image and have a prev/next button for the prev/next image in that category.

My thought was to get the current index for the image itself and have that be the link to the /category/CUR_IMG_ID_PAGINATION_LIST/ as the result of paginating the entire set would yield the same index as the current image index in the paginated results.

For instance if the image i want is image 45 out of 150 images total for a category, then when i paginate the 150 images the 45 will be the actual number of the page I want.

If there's an easier way to do this, let me know. Django 1.1

1

1 Answers

1
votes

I think the way you're describing it would work ok because behind the scenes I believe what Django is doing is using an SQL LIMIT to simply let the database do the heavy lifting of sorting out what and how much data to return. Because the database is optimized for doing this type of thing it's probably a reasonable way to perform this.

The key will probably be to keep the query the same and as you've demonstrated you could use the same view to do that. The view could simply have a mode which is a fancy way of changing the pagination page count.

You could end up with urls like this...

# View all "landscape" items in gallery mode starting on page 3
http://www.example.com/gallery/landscape/multi/3

# View the 45th landscape item in singular mode
http://www.example.com/gallery/landscape/single/45

When the template is rendered, the paginator will offer the has_next and has_previous methods letting you know if you can use render a Next/Previous link.

Here's what I'm thinking for the view, or something along these lines (this is totally un-tested and written off the top of my head)...

url(r'gallery/(?P<category>.+)/(?P<mode>.+)/(?P<offset>\d+)$', 'whatever.views.media_gallery'),

def media_gallery(request, category, mode, offset):
    """
    Render a media gallery.
    category = media item category filter
    mode = ( multi | single )
    offset = The pagination offset in multi mode or the media ID in single mode
    """

    if mode == 'multi':
        per_page = 20   # or however many items per page

    elif mode == 'single':
        per_page = 1
    else:
        pass    # handle this however

    # Queryitems
    raw_media_items = Media.objects.filter(category=category)

    # Setup paginator
    paginator = Paginator(raw_media_items, per_page)

    try:
        # in multi mode offset is the page offset
        # in single mode offset is the media ID
        page = int(offset)
    except:
        page = 1

    try:
        media_items = paginator.page(page)
    except (EmptyPage, InvalidPage):
        media_items = paginator.page(paginator.num_pages)

    if len(paginated_items) == 1:
        # Render single view
        return render_to_response('gallery/gallery_view.html',
                                  { 'media_item':media_items[0], 'paginator':paginator  },
                                  context_instance=RequestContext(request) )
    else:
        # Render gallery view
        return render_to_response('gallery/gallery_view.html',
                                  { 'media_items':media_items, 'paginator':paginator },
                                  context_instance=RequestContext(request) )