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;
+}
--- /dev/null
+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)
+
--- /dev/null
+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)
--- /dev/null
+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)
--- /dev/null
+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 {}
--- /dev/null
+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)
--- /dev/null
+{% 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 %}
--- /dev/null
+{% 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;"> </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 %}
--- /dev/null
+{% 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;"> </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 %}
--- /dev/null
+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'),
+)
--- /dev/null
+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 })
'bpcms',
'generic',
'blog',
+ 'photo',
)
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
(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'))
{% 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 %}