annotate gpp/potd/models.py @ 318:c550933ff5b6

Fix a bug where you'd get an error when trying to delete a forum thread (topic does not exist). Apparently when you call topic.delete() the posts would get deleted, but the signal handler for each one would run, and it would try to update the topic's post count or something, but the topic was gone? Reworked the code a bit and explicitly delete the posts first. I also added a sync() call on the parent forum since post counts were not getting adjusted.
author Brian Neal <bgneal@gmail.com>
date Sat, 05 Feb 2011 21:46:52 +0000
parents 5c889b587416
children 3c951521e0ec
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):
gremmie@1 48
gremmie@1 49 if self.thumb:
gremmie@1 50 self.thumb.delete(save=False)
gremmie@1 51
gremmie@1 52 parser = ImageFile.Parser()
gremmie@1 53 for chunk in self.photo.chunks():
gremmie@1 54 parser.feed(chunk)
gremmie@1 55 image = parser.close()
gremmie@1 56 format = image.format
gremmie@1 57 image = scale_image(image)
gremmie@1 58 s = StringIO()
gremmie@1 59 image.save(s, format)
gremmie@1 60 thumb_name = os.path.basename(self.photo.path)
gremmie@1 61 self.thumb.save(thumb_name, ContentFile(s.getvalue()), save=False)
gremmie@1 62
bgneal@182 63 super(Photo, self).save(*args, **kwargs)
gremmie@1 64 Sequence.objects.insert_photo(self.pk)
gremmie@1 65
gremmie@1 66 def delete(self):
gremmie@1 67 Sequence.objects.remove_photo(self.pk)
gremmie@1 68 super(Photo, self).delete()
gremmie@1 69
gremmie@1 70 def can_comment_on(self):
gremmie@1 71 return Current.objects.get_current_id() == self.id
gremmie@1 72
gremmie@1 73
gremmie@1 74 class CurrentManager(models.Manager):
gremmie@1 75 def get_current_photo(self):
gremmie@1 76 try:
gremmie@1 77 c = self.get(pk=1)
gremmie@1 78 return c.potd
gremmie@1 79 except Current.DoesNotExist:
gremmie@1 80 return None
gremmie@1 81
gremmie@1 82 def get_current_id(self):
gremmie@1 83 potd = self.get_current_photo()
gremmie@1 84 if potd is not None:
gremmie@1 85 return potd.pk
gremmie@1 86 return None
gremmie@1 87
gremmie@1 88
gremmie@1 89 class Current(models.Model):
gremmie@1 90 """This model simply stores the current POTD."""
gremmie@1 91 potd = models.ForeignKey(Photo)
gremmie@1 92
gremmie@1 93 objects = CurrentManager()
gremmie@1 94
gremmie@1 95 def __unicode__(self):
gremmie@1 96 return self.potd.__unicode__()
gremmie@1 97
gremmie@1 98 class Meta:
gremmie@1 99 verbose_name_plural = 'Current'
gremmie@1 100
gremmie@1 101
gremmie@1 102 class SequenceManager(models.Manager):
gremmie@1 103 def insert_photo(self, photo_id):
gremmie@1 104 current = Current.objects.get_current_id()
gremmie@1 105 if current is not None:
gremmie@1 106 try:
gremmie@1 107 s = self.get(pk=1)
gremmie@1 108 seq = [int(x) for x in s.seq.split(',')]
gremmie@1 109 if photo_id not in seq:
gremmie@1 110 i = seq.index(current)
gremmie@1 111 seq.insert(i + 1, photo_id)
gremmie@1 112 s.seq = ','.join([str(x) for x in seq])
gremmie@1 113 s.save()
gremmie@1 114 except:
gremmie@1 115 pass
gremmie@1 116
gremmie@1 117 def remove_photo(self, photo_id):
gremmie@1 118 try:
gremmie@1 119 s = self.get(pk=1)
gremmie@1 120 seq = [int(x) for x in s.seq.split(',')]
gremmie@1 121 if photo_id in seq:
gremmie@1 122 seq.remove(photo_id)
gremmie@1 123 s.seq = ','.join([str(x) for x in seq])
gremmie@1 124 s.save()
gremmie@1 125 except:
gremmie@1 126 pass
gremmie@1 127
gremmie@1 128
gremmie@1 129 class Sequence(models.Model):
gremmie@1 130 """This model stores the sequence of photos for the POTD."""
gremmie@1 131 seq = models.CommaSeparatedIntegerField(max_length=4096)
gremmie@1 132
gremmie@1 133 objects = SequenceManager()
gremmie@1 134
gremmie@1 135 def __unicode__(self):
gremmie@1 136 return self.seq
gremmie@1 137
gremmie@1 138 class Meta:
gremmie@1 139 verbose_name_plural = 'Sequence'
gremmie@1 140