annotate gpp/potd/models.py @ 470:d9b6c4ec1977

For #227; rework last commit slightly (r508). Adapt the desired forums signal signature to the queued_search API instead of the other way around.
author Brian Neal <bgneal@gmail.com>
date Wed, 17 Aug 2011 01:29:27 +0000
parents 3c951521e0ec
children 7dbdbb08e68c
rev   line source
gremmie@1 1 """
gremmie@1 2 Models for the Photo Of The Day (POTD) application.
gremmie@1 3 """
gremmie@1 4 import os
gremmie@1 5 from PIL import ImageFile
gremmie@1 6 from PIL import Image
gremmie@1 7 try:
gremmie@1 8 from cStringIO import StringIO
gremmie@1 9 except:
gremmie@1 10 from StringIO import StringIO
gremmie@1 11
gremmie@1 12 from django.db import models
gremmie@1 13 from django.contrib.auth.models import User
gremmie@1 14 from django.core.files.base import ContentFile
gremmie@1 15
gremmie@1 16 POTD_THUMB_WIDTH = 120
gremmie@1 17
gremmie@1 18 def scale_image(image):
gremmie@1 19 (w, h) = image.size
gremmie@1 20 if w <= POTD_THUMB_WIDTH:
gremmie@1 21 return image
gremmie@1 22 scale_factor = float(POTD_THUMB_WIDTH) / w
gremmie@1 23 new_height = int(scale_factor * h)
gremmie@1 24 return image.resize((POTD_THUMB_WIDTH, new_height), Image.ANTIALIAS)
gremmie@1 25
gremmie@1 26
gremmie@1 27 class Photo(models.Model):
gremmie@1 28 """Model to represent a POTD"""
gremmie@1 29 photo = models.ImageField(upload_to='potd/%Y/%m/%d')
gremmie@1 30 thumb = models.ImageField(upload_to='potd/%Y/%m/%d/thumbs', blank=True, null=True)
gremmie@1 31 caption = models.CharField(max_length=128)
gremmie@1 32 description = models.TextField()
gremmie@1 33 user = models.ForeignKey(User)
gremmie@1 34 date_added = models.DateField(auto_now_add=True)
gremmie@1 35 potd_count = models.IntegerField(default=0)
gremmie@1 36
bgneal@14 37 class Meta:
bgneal@14 38 ordering = ('-date_added', '-caption')
bgneal@14 39
gremmie@1 40 def __unicode__(self):
gremmie@1 41 return u'%s (%s)' % (self.caption, self.pk)
gremmie@1 42
bgneal@14 43 @models.permalink
bgneal@14 44 def get_absolute_url(self):
bgneal@14 45 return ('potd-archive', [str(self.id)])
gremmie@1 46
bgneal@182 47 def save(self, *args, **kwargs):
bgneal@330 48 if not self.pk:
bgneal@330 49 self.generate_thumb()
gremmie@1 50
bgneal@330 51 super(Photo, self).save(*args, **kwargs)
bgneal@330 52 Sequence.objects.insert_photo(self.pk)
bgneal@330 53
bgneal@330 54 def delete(self):
bgneal@330 55 Sequence.objects.remove_photo(self.pk)
bgneal@330 56 super(Photo, self).delete()
bgneal@330 57
bgneal@330 58 def can_comment_on(self):
bgneal@330 59 return Current.objects.get_current_id() == self.id
bgneal@330 60
bgneal@330 61 def generate_thumb(self):
gremmie@1 62 if self.thumb:
gremmie@1 63 self.thumb.delete(save=False)
gremmie@1 64
gremmie@1 65 parser = ImageFile.Parser()
gremmie@1 66 for chunk in self.photo.chunks():
gremmie@1 67 parser.feed(chunk)
gremmie@1 68 image = parser.close()
gremmie@1 69 format = image.format
gremmie@1 70 image = scale_image(image)
gremmie@1 71 s = StringIO()
gremmie@1 72 image.save(s, format)
gremmie@1 73 thumb_name = os.path.basename(self.photo.path)
gremmie@1 74 self.thumb.save(thumb_name, ContentFile(s.getvalue()), save=False)
gremmie@1 75
gremmie@1 76
gremmie@1 77 class CurrentManager(models.Manager):
gremmie@1 78 def get_current_photo(self):
gremmie@1 79 try:
gremmie@1 80 c = self.get(pk=1)
gremmie@1 81 return c.potd
gremmie@1 82 except Current.DoesNotExist:
gremmie@1 83 return None
gremmie@1 84
gremmie@1 85 def get_current_id(self):
gremmie@1 86 potd = self.get_current_photo()
gremmie@1 87 if potd is not None:
gremmie@1 88 return potd.pk
gremmie@1 89 return None
gremmie@1 90
gremmie@1 91
gremmie@1 92 class Current(models.Model):
gremmie@1 93 """This model simply stores the current POTD."""
gremmie@1 94 potd = models.ForeignKey(Photo)
gremmie@1 95
gremmie@1 96 objects = CurrentManager()
gremmie@1 97
gremmie@1 98 def __unicode__(self):
gremmie@1 99 return self.potd.__unicode__()
gremmie@1 100
gremmie@1 101 class Meta:
gremmie@1 102 verbose_name_plural = 'Current'
gremmie@1 103
gremmie@1 104
gremmie@1 105 class SequenceManager(models.Manager):
gremmie@1 106 def insert_photo(self, photo_id):
gremmie@1 107 current = Current.objects.get_current_id()
gremmie@1 108 if current is not None:
bgneal@330 109 s = self.get(pk=1)
bgneal@330 110 seq = [int(x) for x in s.seq.split(',')]
bgneal@330 111 if photo_id not in seq:
bgneal@330 112 i = seq.index(current)
bgneal@330 113 seq.insert(i + 1, photo_id)
bgneal@330 114 s.seq = ','.join([str(x) for x in seq])
bgneal@330 115 s.save()
gremmie@1 116
gremmie@1 117 def remove_photo(self, photo_id):
gremmie@1 118 try:
gremmie@1 119 s = self.get(pk=1)
bgneal@330 120 except Sequence.DoesNotExist:
bgneal@330 121 pass
bgneal@330 122 else:
gremmie@1 123 seq = [int(x) for x in s.seq.split(',')]
gremmie@1 124 if photo_id in seq:
gremmie@1 125 seq.remove(photo_id)
gremmie@1 126 s.seq = ','.join([str(x) for x in seq])
gremmie@1 127 s.save()
gremmie@1 128
gremmie@1 129
gremmie@1 130 class Sequence(models.Model):
gremmie@1 131 """This model stores the sequence of photos for the POTD."""
gremmie@1 132 seq = models.CommaSeparatedIntegerField(max_length=4096)
gremmie@1 133
gremmie@1 134 objects = SequenceManager()
gremmie@1 135
gremmie@1 136 def __unicode__(self):
gremmie@1 137 return self.seq
gremmie@1 138
gremmie@1 139 class Meta:
gremmie@1 140 verbose_name_plural = 'Sequence'
gremmie@1 141