Django Photo Gallery

basic photo gallery built with the Django web framework

Django 1.x, Python 2.5.x

Django Views

gallery-related Django views

from django.shortcuts import render_to_response as render
from django.core.paginator import Paginator, InvalidPage, EmptyPage
from x.public.models import *
from x.public.view_extras import *
#^set_method, increase_popularity, paginate, category_banner, page_banner, page_meta

def port(request):
    m = page_meta("portfolio")
    b = page_banner("portfolio")
    latest = Image.objects.order_by("-pub_date")[:3]
    most_popular = Image.objects.order_by("hits")[:3]

    return render('port_default.html', { 'banner':b, 'latest_images':latest, 'most_popular':most_popular, 'page':m })


# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

def port_cat(request, cat, page='1', method=''):
    m = page_meta("portfolio")
    try:
        increase_popularity(Category, cat=cat)
    except:
        pass

    b = category_banner(cat)
    latest = Image.objects.exclude(category__category__exact=cat).order_by("-pub_date")[:6]

    order = set_method(method)
    image_list = Image.objects.filter(category__category__exact=cat).order_by(order)
    images = paginate(image_list, page, 30)

    return render('port_cat.html',
        { 'banner':b, 'cat':cat, 'images':images, 'latest_images':latest, 'page':page, 'method':method, 'page':m })

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

def port_pic(request, cat, pic, page='1', method=''):
    m = page_meta("portfolio")
    try:
        increase_popularity(Image, pic=pic)
    except:
        pass

    b = category_banner(cat)
    image = Image.objects.select_related().get(id=pic)

    if page:
        order = set_method(method)
        image_list = Image.objects.filter(category__category__exact=cat).order_by(order)
        sbi = paginate(image_list, page, 30)
    else:
        sbi = Image.objects.filter(category__category__exact=cat).exclude(id=pic).order_by("hits")[:12]

    return render('port_pic.html', { 'banner':b, 'cat':cat, 'image':image, 'page':page,
                                     'method':method, 'sbimages':sbi, 'page':m })

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

def port_filter(request, category, method, limit):
    m = page_meta("portfolio")
    b = category_banner(category)
    order = set_method(method)
    images = Image.objects.filter(category__category__exact=category).order_by(order)[:limit]
    category_images = Image.objects.filter(category__category__exact=category).order_by("id")

    return render('port_filter.html', { 'banner':b, 'images':images, 'category_images':category_images,
                                        'category':category, 'method':method, 'page':m })

Custom View Functions

hand-written view functions. DRY.

from django.core.paginator import Paginator, InvalidPage, EmptyPage
from x.public.models import *

def page_meta(page):
    try:
        m = Page.objects.get(name=page)
    except:
        m = ''
    return m

# @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @

def latest_images_by(order,limit):
    return Image.objects.order_by(order)[:limit]

# @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @

def paginate(image_list, page, limit):
    paginator = Paginator(image_list, limit)

    try:
        page = int(page)
    except ValueError:
        page = 1

    if page <= 0: page = 1

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

    return images

# @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @

def page_banner(page):
    try:
        b = Banner.objects.get(page__name__exact=page)
    except:
        b = ''
    return b

# @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @

def category_banner(cat):
    try:
        b = Banner.objects.get(page__name__exact="category_%s"%cat)
    except:
        try:
            default = Banner.objecs.get(page__name__exact="category_default")
            b = { 'headline':'%s' % default.headline, 'body':'%s' % default.body }
        except:
            b = { 'headline':'portfolio::%s'%cat, 'body':'%s related pics. \
                   These images are sorted by category. To sort portfolio images \
                   by their appropriate set please select the "SORT BY SET" option to the right.'%cat }
    return b

# @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @

def set_method(method):
    order = "id"
    if method == "newest":
        order = "-pub_date"
    elif method == "oldest":
        order = "pub_date"
    elif method == "set":
        order = "-set"
    elif method == "newest":
        order = "-pub_date"
    elif method == "top":
        order = "-hits"

    return order

# @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @ - @

def increase_popularity(MODEL, cat='', pic=''):
    if cat:
        m = MODEL.objects.get(category=cat)
    elif pic:
        m = MODEL.objects.get(id=pic)
    else:
        return False

    m.hits = int(m.hits) + 1
    m.save()

    return True

Related Models

models for photo gallery. uses the awesome sorl thumbnail library

class Category(models.Model):
    page = models.ForeignKey(Page)
    category = models.CharField(max_length=30)
    description = models.TextField()
    hits = models.IntegerField()

    def __unicode__(self):
        return self.category

class Image(models.Model):
    category = models.ForeignKey(Category)
    set = models.CharField(max_length=30, blank=True)
    image = ImageWithThumbnailsField(upload_to='img/content/portfolio', thumbnail={'size':('100','100')}, generate_on_save=True)
    pub_date = models.DateTimeField()
    hits = models.IntegerField()

    def __unicode__(self):
        return u'id:%s | set:%s image:%s' % (self.id, self.set, self.image)

Django Template

a template from the gallery. uses pagination to sort through a category.

{% extends "port_common.html" %}

{% load thumbnail %}

{% block content %}
    {% if images %}
            <h2>{{ cat|title }} Gallery | <span class="h2-small">Page</span> {{ images.number }} 
                <span class="h2-small">of</span> {{ images.paginator.num_pages }} </span> | 
                <span class="h2-small"> Images</span> [{{ images.start_index }} - 
                {{ images.end_index }}] <span class="h2-small"> of </span>{{ images.paginator.count }}
            </h2>


            <div class="paginator">
                {% if images.has_previous %}
                    <a href="/portfolio/{{ cat }}/page/{{ images.previous_page_number }}/{%if method%}by/{{method}}/{%endif%}">
                        <span class="accent">[</span>prev<span class="accent">]</span></a>
                {% endif %}
                {% for page in images.paginator.page_range %}
                    {% ifequal page images.number %}
                        <span class="cur-page">{{ page }}</span>
                    {% else %}
                        <a href="/portfolio/{{ cat }}/page/{{ page }}/">{{ page }}</a>
                    {% endifequal %}
                {% endfor %}
                {% if images.has_next %}
                    <a href="/portfolio/{{ cat }}/page/{{ images.next_page_number }}/{%if method%}by/{{method}}/{%endif%}">
                        <span class="accent">[</span>next<span class="accent">]</span></a>
                {% endif %}
            </div>




            {% for image in images.object_list %}
                <div class="tn-100x100">
                    <a href="/portfolio/{{image.category.category}}/{%if images.number%}page/{{images.number}}/{%endif%}{%if method%}by/{{method}}/{%endif%}pic/{{ image.id }}/">
                        <img src="{% thumbnail image.image 100x100 %}"/></a>
                </div>
            {% endfor %}





            <div class="paginator">
                {% if images.has_previous %}
                    <a href="/portfolio/{{ cat }}/page/{{ images.previous_page_number }}/{%if method%}by/{{method}}/{%endif%}">
                        <span class="accent">[</span>prev<span class="accent">]</span></a>
                {% endif %}
                {% for page in images.paginator.page_range %}
                    {% ifequal page images.number %}
                        <span class="cur-page">{{ page }}</span>
                    {% else %}
                        <a href="/portfolio/{{ cat }}/page/{{ page }}/">{{ page }}</a>
                    {% endifequal %}
                {% endfor %}
                {% if images.has_next %}
                    <a href="/portfolio/{{ cat }}/page/{{ images.next_page_number }}/{%if method%}by/{{method}}/{%endif%}">
                        <span class="accent">[</span>next<span class="accent">]</span></a>
                {% endif %}
            </div>

    {% else %}
        <h3>Category not found!</h3>
        <p>The category you requested could not be retrieved. Either it does not exist, you typed it incorrectly, or something on our end happened. Please try again. If this problem persists please let us know. Thank you.</p>
    {% endif %}
{% endblock %}

{% block options %}
    <h2>Options</h2>
    <form action="" method="get">
        <label for="directive">Order by</label>
        <select name="directive">
            <option value="category">category</option>
            <option value="set">set</option>
            <option value="date_desc">publish date | new-to-old</option>
            <option value="date_asc">publish date | old-to-new</option>
            <option value="comments">most comments</option>
        </select>
    </form>
{% endblock %}

{% block sidebar %}
    <div class="sb-data">
        <h2>Sort category by</h2>
        <div class="sb-option">
            <h3>other</h3>
            <a href="/portfolio/{{cat}}/{%if images.number%}page/{{images.number}}/{%endif%}by/set/">set</a>
        </div>
        <div class="sb-option">
            <h3>date</h3>
            <a href="/portfolio/{{cat}}/{%if images.number%}page/{{images.number}}/{%endif%}by/newest/">newest</a> |
            <a href="/portfolio/{{cat}}/{%if images.number%}page/{{images.number}}/{%endif%}by/oldest/">oldest</a>
        </div>
    </div>
    <div class="sb-data">
        <h2>Show</h2>
        <div class="sb-option">
            <h3>Most Popular</h3>
            <a href="/portfolio/{{cat}}/top/3/">3</a> |
            <a href="/portfolio/{{cat}}/top/6/">6</a> |
            <a href="/portfolio/{{cat}}/top/9/">9</a> |
            <a href="/portfolio/{{cat}}/top/12/">12</a>
        </div>
        <div class="sb-option">
            <h3>Newest</h3>
            <a href="/portfolio/{{cat}}/newest/3/">3</a> |
            <a href="/portfolio/{{cat}}/newest/6/">6</a> |
            <a href="/portfolio/{{cat}}/newest/9/">9</a> |
            <a href="/portfolio/{{cat}}/newest/12/">12</a>
        </div>
    </div>
    {% if latest_images %}
        <div class="sb-data">
            <h2>Newest<br/><span class="sb-h2-small">[from other categories]</span></h2>
            {% for image in latest_images %}
                <div class="img-wrap">
                    <div class="tn-70x70">
                        <a href="/portfolio/{{image.category.category}}/pic/{{ image.id }}/"><img src="{% thumbnail image.image 70x70 %}"/></a>
                    </div>
                    <p>category:<span class="img-info">{{ image.category.category }}</span><br/>
                       image:<span class="img-info">{{ image.id }}</span><br/>
                    {% if image.set %}
                       set:<span class="img-info">{{ image.set }}</span><br/>
                    {% endif %}
                       added:<span class="img-info">{{ image.pub_date|date:"D, M Y" }}</span>
                    </p>
                </div>
            {% endfor %}
        </div>
    {% endif %}
{% endblock %}