From d82db041f520a51eccee6788ebc3a494e2a4280f Mon Sep 17 00:00:00 2001 From: Brett Parker Date: Sun, 29 Mar 2009 14:48:05 +0100 Subject: [PATCH] First draft image gallery --- media/style/main.css | 22 ++++ sommitrealweird/generic/helpers.py | 100 ++++++++++++++++++ .../generic/templatetags/__init__.py | 0 .../generic/templatetags/thumbnail.py | 37 +++++++ sommitrealweird/photo/__init__.py | 0 sommitrealweird/photo/admin.py | 8 ++ sommitrealweird/photo/context_processors.py | 30 ++++++ sommitrealweird/photo/models.py | 29 +++++ .../photo/templates/photo/album_index.html | 38 +++++++ .../photo/templates/photo/photo.html | 20 ++++ .../photo/templates/photo/photo_index.html | 39 +++++++ sommitrealweird/photo/urls.py | 8 ++ sommitrealweird/photo/views.py | 30 ++++++ sommitrealweird/settings.py | 2 + sommitrealweird/urls.py | 1 + templates/base.html | 2 +- 16 files changed, 365 insertions(+), 1 deletion(-) create mode 100644 sommitrealweird/generic/helpers.py create mode 100644 sommitrealweird/generic/templatetags/__init__.py create mode 100644 sommitrealweird/generic/templatetags/thumbnail.py create mode 100644 sommitrealweird/photo/__init__.py create mode 100644 sommitrealweird/photo/admin.py create mode 100644 sommitrealweird/photo/context_processors.py create mode 100644 sommitrealweird/photo/models.py create mode 100644 sommitrealweird/photo/templates/photo/album_index.html create mode 100644 sommitrealweird/photo/templates/photo/photo.html create mode 100644 sommitrealweird/photo/templates/photo/photo_index.html create mode 100644 sommitrealweird/photo/urls.py create mode 100644 sommitrealweird/photo/views.py diff --git a/media/style/main.css b/media/style/main.css index 65413bb..3efdb8e 100644 --- a/media/style/main.css +++ b/media/style/main.css @@ -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 index 0000000..6c85aa1 --- /dev/null +++ b/sommitrealweird/generic/helpers.py @@ -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 index 0000000..e69de29 diff --git a/sommitrealweird/generic/templatetags/thumbnail.py b/sommitrealweird/generic/templatetags/thumbnail.py new file mode 100644 index 0000000..4e20cef --- /dev/null +++ b/sommitrealweird/generic/templatetags/thumbnail.py @@ -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 index 0000000..e69de29 diff --git a/sommitrealweird/photo/admin.py b/sommitrealweird/photo/admin.py new file mode 100644 index 0000000..90c48b2 --- /dev/null +++ b/sommitrealweird/photo/admin.py @@ -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 index 0000000..b00e5e1 --- /dev/null +++ b/sommitrealweird/photo/context_processors.py @@ -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 index 0000000..1e2cc68 --- /dev/null +++ b/sommitrealweird/photo/models.py @@ -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 index 0000000..edfbc9f --- /dev/null +++ b/sommitrealweird/photo/templates/photo/album_index.html @@ -0,0 +1,38 @@ +{% extends "base.html" %} +{% load thumbnail %} +{% load markup %} + +{% block content %} + {% if object_list %} + {% for album in object_list %} +
+ {{ album.get_main_image.caption }} +

{{ album.name }}

+

{{ album.caption }} +

+ {% endfor %} + {% if is_paginated %} +

Pages: + {% if page_obj.has_previous %} + Previous | + {% endif %} + {% for paginator_page in paginator.page_range %} + {% if forloop.first %} + {% else %} + | + {% endif %} + {% ifequal paginator_page page %} + {{ page }} + {% else %} + {{ paginator_page }} + {% endifequal %} + {% endfor %} + {% if page_obj.has_next %} + | Next + {% endif %} +

+ {% endif %} + {% else %} +

There are no photo albums available.

+ {% endif %} +{% endblock %} diff --git a/sommitrealweird/photo/templates/photo/photo.html b/sommitrealweird/photo/templates/photo/photo.html new file mode 100644 index 0000000..513cd73 --- /dev/null +++ b/sommitrealweird/photo/templates/photo/photo.html @@ -0,0 +1,20 @@ +{% extends "base.html" %} +{% load thumbnail %} + +{% block content %} +
+ {{ object.caption }} +

{{ object.caption }} +

+
 
+ {% if prev_photo or next_photo%} +

+ {% if prev_photo %} + Previous + {% endif %} + {% if next_photo %} + Next + {% endif %} +

+ {% endif %} +{% endblock %} diff --git a/sommitrealweird/photo/templates/photo/photo_index.html b/sommitrealweird/photo/templates/photo/photo_index.html new file mode 100644 index 0000000..573d6fe --- /dev/null +++ b/sommitrealweird/photo/templates/photo/photo_index.html @@ -0,0 +1,39 @@ +{% extends "base.html" %} +{% load thumbnail %} + +{% block content %} + {% if object_list %} +

{{ object_list.0.album.name }}

+
{{ object_list.0.album.caption }}
+ {% for photo in object_list %} +
+ {{ photo.caption }} +

{{ photo.caption }} +

+ {% endfor %} +
 
+ {% if is_paginated %} +

Pages: + {% if page_obj.has_previous %} + Previous | + {% endif %} + {% for paginator_page in paginator.page_range %} + {% if forloop.first %} + {% else %} + | + {% endif %} + {% ifequal paginator_page page %} + {{ page }} + {% else %} + {{ paginator_page }} + {% endifequal %} + {% endfor %} + {% if page_obj.has_next %} + | Next + {% endif %} +

+ {% endif %} + {% else %} +

There are no photos available.

+ {% endif %} +{% endblock %} diff --git a/sommitrealweird/photo/urls.py b/sommitrealweird/photo/urls.py new file mode 100644 index 0000000..8a17fd3 --- /dev/null +++ b/sommitrealweird/photo/urls.py @@ -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[^/]*)/$', 'photo.views.album_view'), + (r'^(?P[^/]*)/(?P[0-9]+)/$', 'photo.views.photo_view'), +) diff --git a/sommitrealweird/photo/views.py b/sommitrealweird/photo/views.py new file mode 100644 index 0000000..920b1da --- /dev/null +++ b/sommitrealweird/photo/views.py @@ -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 }) diff --git a/sommitrealweird/settings.py b/sommitrealweird/settings.py index d20abe4..e4d2dcc 100644 --- a/sommitrealweird/settings.py +++ b/sommitrealweird/settings.py @@ -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 diff --git a/sommitrealweird/urls.py b/sommitrealweird/urls.py index 6eb6f42..23c848c 100644 --- a/sommitrealweird/urls.py +++ b/sommitrealweird/urls.py @@ -24,6 +24,7 @@ urlpatterns = patterns('', (r'^media/(?P.*)$', '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.*)/', 'django.contrib.syndication.views.feed', {'feed_dict': rssfeeds_dict}), (r'^feeds/(?P.*)/', 'django.contrib.syndication.views.feed', {'feed_dict': feeds_dict}), (r'^(?:content/|)', include('bpcms.urls')) diff --git a/templates/base.html b/templates/base.html index 430b8c6..ee565e1 100644 --- a/templates/base.html +++ b/templates/base.html @@ -18,7 +18,7 @@ {% for item in content_menu %}
  • {{ item.title }}
  • {% endfor %} -
  • Photos
  • +
  • Photos
  • Blog
  • {% endblock %} -- 2.30.2