First draft image gallery
authorBrett Parker <iDunno@sommitrealweird.co.uk>
Sun, 29 Mar 2009 13:48:05 +0000 (14:48 +0100)
committerBrett Parker <iDunno@sommitrealweird.co.uk>
Sun, 29 Mar 2009 13:48:05 +0000 (14:48 +0100)
16 files changed:
media/style/main.css
sommitrealweird/generic/helpers.py [new file with mode: 0644]
sommitrealweird/generic/templatetags/__init__.py [new file with mode: 0644]
sommitrealweird/generic/templatetags/thumbnail.py [new file with mode: 0644]
sommitrealweird/photo/__init__.py [new file with mode: 0644]
sommitrealweird/photo/admin.py [new file with mode: 0644]
sommitrealweird/photo/context_processors.py [new file with mode: 0644]
sommitrealweird/photo/models.py [new file with mode: 0644]
sommitrealweird/photo/templates/photo/album_index.html [new file with mode: 0644]
sommitrealweird/photo/templates/photo/photo.html [new file with mode: 0644]
sommitrealweird/photo/templates/photo/photo_index.html [new file with mode: 0644]
sommitrealweird/photo/urls.py [new file with mode: 0644]
sommitrealweird/photo/views.py [new file with mode: 0644]
sommitrealweird/settings.py
sommitrealweird/urls.py
templates/base.html

index 65413bbeab9727a783d531102a86ae35f7f6773f..3efdb8e6a5de0c694e964c460cf8d526f7596d5a 100644 (file)
@@ -148,3 +148,25 @@ body #page #footer p {
     padding: 0.1em;
 }
 
+div.album {
+    margin-top: 2em;
+}
+
+div.album a img {
+    border: 0;
+}
+
+div.photo {
+    margin-top: 2em;
+    float: left;
+    margin-right: 2em;
+}
+
+div.single_photo {
+    margin-top: 2em;
+}
+
+div.photo a img,
+div.single_photo a img {
+    border: 0;
+}
diff --git a/sommitrealweird/generic/helpers.py b/sommitrealweird/generic/helpers.py
new file mode 100644 (file)
index 0000000..6c85aa1
--- /dev/null
@@ -0,0 +1,100 @@
+from django.conf import settings
+from PIL import Image
+import os, sys
+
+def make_thumbnail(imagefile,width=None,height=None):
+    # first check that the thumbnail image doesn't already exist
+    # and if it does that it's newer than the origional image
+    
+    base_dir = settings.MEDIA_ROOT
+    thumbs_dir = base_dir
+    if not thumbs_dir.endswith("/"):
+        thumbs_dir = "%s/" %(thumbs_dir,)
+        base_dir = "%s/" %(base_dir,)
+    
+    try:
+        thumbs_dir = "%s%s/" %(thumbs_dir, settings.THUMBS_DIRECTORY)
+        thumbsdirectory = settings.THUMBS_DIRECTORY
+    except:
+        thumbs_dir = "%sthumbs/" %(thumbs_dir,)
+        thumbsdirectory = "thumbs"
+
+    if width != None:
+        try:
+            thumb = os.stat("%sw%d/%s" % (thumbs_dir, width, imagefile))
+            pic = os.stat("%s%s" % (base_dir, imagefile))
+            if thumb.st_ctime < pic.st_ctime:
+                # regenerate the icon
+                img = Image.open("%s%s" %(base_dir, imagefile))
+                (curwidth,curheight) = img.size
+
+                newwidth = width
+                newheight = int((newwidth * curheight) / curwidth)
+
+                newimg = img.resize((newwidth, newheight))
+                newimg.save("%sw%d/%s" %(thumbs_dir, width, imagefile))
+                
+                return "%s%s/w%d/%s" %(settings.MEDIA_URL, thumbsdirectory, width, imagefile)
+            else:
+                # we have a winner!
+                return "%s%s/w%d/%s" %(settings.MEDIA_URL, thumbsdirectory, width, imagefile)
+        except:
+            # well, there's not one there. feh. sucks.
+            try:
+                directory_to_create = imagefile[:imagefile.rindex(os.sep)]
+                img = Image.open("%s%s" %(base_dir, imagefile))
+                if not os.path.isdir("%sw%d/%s" %(thumbs_dir, width, directory_to_create)):
+                    os.makedirs("%sw%d/%s" %(thumbs_dir, width, directory_to_create))
+                (curwidth,curheight) = img.size
+
+                newwidth = width
+                newheight = int((newwidth * curheight) / curwidth)
+
+                newimg = img.resize((newwidth, newheight))
+                newimg.save("%sw%d/%s" %(thumbs_dir, width, imagefile))
+                
+                return "%s%s/w%d/%s" %(settings.MEDIA_URL, thumbsdirectory, width, imagefile)
+            except Exception, e:
+                sys.stderr.write("Got exception: %s" %(e,))
+
+    elif height != None:
+        try:
+            thumb = os.stat("%sh%d/%s" % (thumbs_dir, height, imagefile))
+            pic = os.stat("%s%s" % (base_dir, imagefile))
+            if thumb.st_ctime < pic.st_ctime:
+                # regenerate the icon
+                img = Image.open("%s%s" %(base_dir, imagefile))
+                (curwidth,curheight) = img.size
+
+                newheight = height
+                newheight = int((newheight * curwidth) / curheight)
+
+                newimg = img.resize((newwidth, newheight))
+                newimg.save("%sh%d/%s" %(thumbs_dir, height, imagefile))
+                
+                return "%s%s/h%d/%s" %(settings.MEDIA_URL, thumbsdirectory, height, imagefile)
+            else:
+                # we have a winner!
+                return "%s%s/h%d/%s" %(settings.MEDIA_URL, thumbsdirectory, height, imagefile)
+        except:
+            # well, there's not one there. feh. sucks.
+            try:
+                directory_to_create = imagefile[:imagefile.rindex(os.sep)]
+                img = Image.open("%s%s" %(base_dir, imagefile))
+                os.makedirs("%sh%h/%s" %(thumbs_dir, height, directory_to_create))
+                (curwidth,curheight) = img.size
+
+                newheight = height
+                newwidth = int((newheight * curwidth) / curheight)
+
+                newimg = img.resize((newwidth, newheight))
+                newimg.save("%sh%d/%s" %(thumbs_dir, height, imagefile))
+                
+                return "%s%s/h%d/%s" %(settings.MEDIA_URL, thumbsdirectory, height, imagefile)
+            except:
+                pass
+
+    # if everything fails, we'll return the origional image URL
+    # this is for simpilicity
+    return "%s%s" %(settings.MEDIA_URL, imagefile)
+
diff --git a/sommitrealweird/generic/templatetags/__init__.py b/sommitrealweird/generic/templatetags/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/sommitrealweird/generic/templatetags/thumbnail.py b/sommitrealweird/generic/templatetags/thumbnail.py
new file mode 100644 (file)
index 0000000..4e20cef
--- /dev/null
@@ -0,0 +1,37 @@
+from django import template
+from django.conf import settings
+from generic import helpers
+import sys
+
+register = template.Library()
+
+def thumbnail(image_url, args=''):
+    options = {}
+
+    if ',' not in args:
+        args = "%s," %(args,)
+
+    for arg in args.split(','):
+        arg = arg.strip()
+        try:
+            (kw,val) = arg.split('=', 1)
+            try:
+                options[kw] = int(val)
+            except:
+                pass
+        except:
+            pass
+
+    if options.has_key("height") or options.has_key("width"):
+        if options.has_key("width") and options.has_key("height"):
+            return helpers.make_thumbnail(image_url[len(settings.MEDIA_URL):], width=options["width"], height=options["height"])
+        elif options.has_key("width"):
+            return helpers.make_thumbnail(image_url[len(settings.MEDIA_URL):], width=options["width"])
+        else:
+            return helpers.make_thumbnail(image_url[len(settings.MEDIA_URL):], height=options["height"])
+    else:
+        pass
+
+    return "%s" %(image_url)
+
+register.filter(thumbnail)
diff --git a/sommitrealweird/photo/__init__.py b/sommitrealweird/photo/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/sommitrealweird/photo/admin.py b/sommitrealweird/photo/admin.py
new file mode 100644 (file)
index 0000000..90c48b2
--- /dev/null
@@ -0,0 +1,8 @@
+from models import Album, Photo
+from django.contrib import admin
+
+class AlbumAdmin(admin.ModelAdmin):
+    prepopulated_fields = { "slug": ("name",) }
+
+admin.site.register(Album, AlbumAdmin)
+admin.site.register(Photo)
diff --git a/sommitrealweird/photo/context_processors.py b/sommitrealweird/photo/context_processors.py
new file mode 100644 (file)
index 0000000..b00e5e1
--- /dev/null
@@ -0,0 +1,30 @@
+from django.conf import settings
+from models import Album, Photo
+import re
+
+def content_breadcrumb(request):
+    path = request.path
+    if path[0:6] == "/photo":
+        breadcrumb = [{'url': u'/', 'title': u'Home'}, {'url': u'/photo/', 'title': u'Photos'}]
+        try:
+            path = path[7:]
+            album_slug = path.split('/', 1)[0]
+            album = Album.objects.get(slug__exact=album_slug)
+            breadcrumb.append({'url': u'/photo/%s/' %(album_slug), 'title': album.name})
+            try:
+                rest = path.split('/', 1)[1]
+                if len(rest) > 0:
+                    photo_id = rest.split('/')[0]
+                    photo_id = int(photo_id)
+                    photo = Photo.objects.get(id=photo_id)
+                    breadcrumb.append({'url': request.path, 'title': photo.image.name.split('/')[-1]})
+            except:
+                pass
+        except:
+            pass
+
+        return {
+            'content_breadcrumb': breadcrumb,
+        }
+    else:
+        return {}
diff --git a/sommitrealweird/photo/models.py b/sommitrealweird/photo/models.py
new file mode 100644 (file)
index 0000000..1e2cc68
--- /dev/null
@@ -0,0 +1,29 @@
+from django.db import models
+from django.conf import settings
+
+class Album(models.Model):
+    name = models.CharField(max_length=120)
+    caption = models.TextField(blank=True, null=True)
+    slug = models.SlugField()
+
+    def get_main_image(self):
+        main_photo = Photo.objects.filter(album=self).order_by('order','image')[0]
+        return main_photo.image
+
+    def __unicode__(self):
+        return "%s" %(self.name,)
+
+def get_upload_path(photo, filename):
+    if photo.album:
+        return "photos/%s/%s" %(photo.album.slug, filename)
+    else:
+        return "photos/%s" %(filename)
+
+class Photo(models.Model):
+    image = models.ImageField(upload_to=get_upload_path, null=True)
+    caption = models.TextField(blank=True, null=True)
+    order = models.IntegerField(blank=True, null=True)
+    album = models.ForeignKey('Album')
+
+    def __unicode__(self):
+        return "%s" %(self.image)
diff --git a/sommitrealweird/photo/templates/photo/album_index.html b/sommitrealweird/photo/templates/photo/album_index.html
new file mode 100644 (file)
index 0000000..edfbc9f
--- /dev/null
@@ -0,0 +1,38 @@
+{% extends "base.html" %}
+{% load thumbnail %}
+{% load markup %}
+
+{% block content %}
+    {% if object_list %}
+        {% for album in object_list %}
+            <div class="album">
+                <a href="{{ album.slug }}/"><img src="{{ album.get_main_image.url|thumbnail:"width=250" }}" alt="{{ album.get_main_image.caption }}" /></a>
+                <h2><a href="{{ album.slug }}/">{{ album.name }}</a></h2>
+                <p>{{ album.caption }}</h2>
+            </div>
+        {% endfor %}
+        {% if is_paginated %}
+            <p class="paginator">Pages: 
+            {% if page_obj.has_previous %}
+                <a href="?page={{ page_obj.previous_page_number }}">Previous</a> |
+            {% endif %}
+            {% for paginator_page in paginator.page_range %}
+                {% if forloop.first %}
+                {% else %}
+                    |
+                {% endif %}
+                {% ifequal paginator_page page %}
+                    {{ page }}
+                {% else %}
+                    <a href="?page={{ paginator_page }}">{{ paginator_page }}</a>
+                {% endifequal %}
+            {% endfor %}
+            {% if page_obj.has_next %}
+                | <a href="?page={{ page_obj.next_page_number }}">Next</a>
+            {% endif %}
+            </p>
+        {% endif %}
+    {% else %}
+        <p>There are no photo albums available.</p>
+    {% endif %}
+{% endblock %}
diff --git a/sommitrealweird/photo/templates/photo/photo.html b/sommitrealweird/photo/templates/photo/photo.html
new file mode 100644 (file)
index 0000000..513cd73
--- /dev/null
@@ -0,0 +1,20 @@
+{% extends "base.html" %}
+{% load thumbnail %}
+
+{% block content %}
+    <div class="single_photo">
+        <a href="{{ object.image.url }}"><img src='{{ object.image.url|thumbnail:"width=500" }}' alt="{{ object.caption }}" /></a>
+        <p>{{ object.caption }}</h2>
+    </div>
+    <div style="clear: both;">&nbsp;</div>
+    {% if prev_photo or next_photo%}
+        <p class="paginator">
+            {% if prev_photo %}
+                <a href="/photo/{{ object.album.slug }}/{{ prev_photo.id }}/">Previous</a>
+            {% endif %}
+            {% if next_photo %}
+                <a href="/photo/{{ object.album.slug }}/{{ next_photo.id }}/">Next</a>
+            {% endif %}
+        </p>
+    {% endif %}
+{% endblock %}
diff --git a/sommitrealweird/photo/templates/photo/photo_index.html b/sommitrealweird/photo/templates/photo/photo_index.html
new file mode 100644 (file)
index 0000000..573d6fe
--- /dev/null
@@ -0,0 +1,39 @@
+{% extends "base.html" %}
+{% load thumbnail %}
+
+{% block content %}
+    {% if object_list %}
+        <h1>{{ object_list.0.album.name }}</h1>
+        <div class="album_caption">{{ object_list.0.album.caption }}</div>
+        {% for photo in object_list %}
+            <div class="photo">
+                <a href="{{ photo.id }}/"><img src='{{ photo.image.url|thumbnail:"width=250" }}' alt="{{ photo.caption }}" /></a>
+                <p>{{ photo.caption }}</h2>
+            </div>
+        {% endfor %}
+        <div style="clear: both;">&nbsp;</div>
+        {% if is_paginated %}
+            <p class="paginator">Pages: 
+            {% if page_obj.has_previous %}
+                <a href="?page={{ page_obj.previous_page_number }}">Previous</a> |
+            {% endif %}
+            {% for paginator_page in paginator.page_range %}
+                {% if forloop.first %}
+                {% else %}
+                    |
+                {% endif %}
+                {% ifequal paginator_page page %}
+                    {{ page }}
+                {% else %}
+                    <a href="?page={{ paginator_page }}">{{ paginator_page }}</a>
+                {% endifequal %}
+            {% endfor %}
+            {% if page_obj.has_next %}
+                | <a href="?page={{ page_obj.next_page_number }}">Next</a>
+            {% endif %}
+            </p>
+        {% endif %}
+    {% else %}
+        <p>There are no photos available.</p>
+    {% endif %}
+{% endblock %}
diff --git a/sommitrealweird/photo/urls.py b/sommitrealweird/photo/urls.py
new file mode 100644 (file)
index 0000000..8a17fd3
--- /dev/null
@@ -0,0 +1,8 @@
+from django.conf.urls.defaults import *
+from models import Album
+
+urlpatterns = patterns('',
+    (r'^$', 'django.views.generic.list_detail.object_list', { "paginate_by": 20, "queryset": Album.objects.all(), "template_name": "photo/album_index.html"}),
+    (r'^(?P<slug>[^/]*)/$', 'photo.views.album_view'),
+    (r'^(?P<slug>[^/]*)/(?P<id>[0-9]+)/$', 'photo.views.photo_view'),
+)
diff --git a/sommitrealweird/photo/views.py b/sommitrealweird/photo/views.py
new file mode 100644 (file)
index 0000000..920b1da
--- /dev/null
@@ -0,0 +1,30 @@
+import django.views.generic.list_detail
+from django.http import Http404
+from models import Album, Photo
+
+def album_view(request, slug):
+    album = Album.objects.get(slug__exact=slug)
+    photos = Photo.objects.filter(album=album).order_by('order', 'image')
+    return django.views.generic.list_detail.object_list(request, photos, paginate_by=20, template_name='photo/photo_index.html')
+
+def photo_view(request, slug, id):
+    id = int(id)
+    album = Album.objects.get(slug__exact=slug)
+    photos = Photo.objects.filter(album=album).order_by('order', 'image')
+    photo_qs = Photo.objects.filter(id=id)
+    found_prev = False
+    prev_photo = None
+    found_next = False
+    next_photo = None
+    for photo in photos:
+        if not found_prev:
+            if not photo.id == id:
+                prev_photo = photo
+            else:
+                found_prev = True
+        if found_next:
+            next_photo = photo
+            break
+        if photo.id == id:
+            found_next = True
+    return django.views.generic.list_detail.object_detail(request, photo_qs, object_id=id, template_name='photo/photo.html', extra_context={"next_photo": next_photo, "prev_photo": prev_photo })
index d20abe445a96a882b89261c9f7ca69ba8bac41ac..e4d2dcccd43addd35e6552c2b6a6b05997e770aa 100644 (file)
@@ -70,6 +70,7 @@ INSTALLED_APPS = (
     'bpcms',
     'generic',
     'blog',
+    'photo',
 )
 
 TEMPLATE_CONTEXT_PROCESSORS = (
@@ -81,6 +82,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
     'bpcms.context_processors.content_submenu',
     'bpcms.context_processors.content_breadcrumb',
     'blog.context_processors.content_breadcrumb',
+    'photo.context_processors.content_breadcrumb',
 )
 
 APPEND_SLASH=False
index 6eb6f423e05b10ac9538d4a209b84d8ef433daec..23c848ccf6e54de525e676afc63479b51092d6bb 100644 (file)
@@ -24,6 +24,7 @@ urlpatterns = patterns('',
     (r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': MEDIA_ROOT, 'show_indexes': True}),
     (r'^admin/(.*)$', admin.site.root),
     (r'^blog/', include('blog.urls')),
+    (r'^photo/', include('photo.urls')),
     (r'^feeds/rss/(?P<url>.*)/', 'django.contrib.syndication.views.feed', {'feed_dict': rssfeeds_dict}),
     (r'^feeds/(?P<url>.*)/', 'django.contrib.syndication.views.feed', {'feed_dict': feeds_dict}),
     (r'^(?:content/|)', include('bpcms.urls'))
index 430b8c669211e4619b2d480ee3b289df9f4b5bd0..ee565e117bc45884d7d802a130bce276e1ed4e5c 100644 (file)
@@ -18,7 +18,7 @@
                         {% for item in content_menu %}
                         <li><a href="{{ item.url }}">{{ item.title }}</a></li>
                         {% endfor %}
-                        <li>Photos</li>
+                        <li><a href="/photo/">Photos</a></li>
                         <li><a href="/blog/">Blog</a></li>
                     </ul>
                     {% endblock %}