annotate gpp/potd/models.py @ 467:b910cc1460c8

Add the ability to conditionally add model instances to the search index on update. This is not perfect, as some instances should be deleted from the index if they are updated such that they should not be in the index anymore. Will think about and address that later.
author Brian Neal <bgneal@gmail.com>
date Sun, 24 Jul 2011 18:12:20 +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