annotate potd/models.py @ 1206:02181fa5ac9d modernize tip

Update to Django 1.9.
author Brian Neal <bgneal@gmail.com>
date Wed, 22 Jan 2025 17:58:16 -0600
parents eeaf387803c6
children
rev   line source
gremmie@1 1 """
gremmie@1 2 Models for the Photo Of The Day (POTD) application.
bgneal@515 3
gremmie@1 4 """
bgneal@535 5 import datetime
gremmie@1 6 import os
gremmie@1 7 from PIL import ImageFile
gremmie@1 8 from PIL import Image
gremmie@1 9 try:
gremmie@1 10 from cStringIO import StringIO
gremmie@1 11 except:
gremmie@1 12 from StringIO import StringIO
gremmie@1 13
gremmie@1 14 from django.db import models
gremmie@1 15 from django.contrib.auth.models import User
gremmie@1 16 from django.core.files.base import ContentFile
bgneal@1035 17 from django.core.urlresolvers import reverse
gremmie@1 18
gremmie@1 19 POTD_THUMB_WIDTH = 120
gremmie@1 20
gremmie@1 21 def scale_image(image):
gremmie@1 22 (w, h) = image.size
gremmie@1 23 if w <= POTD_THUMB_WIDTH:
gremmie@1 24 return image
gremmie@1 25 scale_factor = float(POTD_THUMB_WIDTH) / w
gremmie@1 26 new_height = int(scale_factor * h)
gremmie@1 27 return image.resize((POTD_THUMB_WIDTH, new_height), Image.ANTIALIAS)
gremmie@1 28
gremmie@1 29
gremmie@1 30 class Photo(models.Model):
gremmie@1 31 """Model to represent a POTD"""
gremmie@1 32 photo = models.ImageField(upload_to='potd/%Y/%m/%d')
gremmie@1 33 thumb = models.ImageField(upload_to='potd/%Y/%m/%d/thumbs', blank=True, null=True)
gremmie@1 34 caption = models.CharField(max_length=128)
gremmie@1 35 description = models.TextField()
bgneal@1206 36 user = models.ForeignKey(User, related_name='potd_set',
bgneal@1206 37 on_delete=models.CASCADE)
bgneal@535 38 date_added = models.DateField()
gremmie@1 39 potd_count = models.IntegerField(default=0)
gremmie@1 40
bgneal@14 41 class Meta:
bgneal@14 42 ordering = ('-date_added', '-caption')
bgneal@14 43
gremmie@1 44 def __unicode__(self):
gremmie@1 45 return u'%s (%s)' % (self.caption, self.pk)
gremmie@1 46
bgneal@14 47 def get_absolute_url(self):
bgneal@1035 48 return reverse('potd-archive', args=[str(self.id)])
gremmie@1 49
bgneal@182 50 def save(self, *args, **kwargs):
bgneal@330 51 if not self.pk:
bgneal@330 52 self.generate_thumb()
bgneal@535 53 self.date_added = datetime.datetime.now()
gremmie@1 54
bgneal@330 55 super(Photo, self).save(*args, **kwargs)
bgneal@330 56
bgneal@330 57 def can_comment_on(self):
bgneal@330 58 return Current.objects.get_current_id() == self.id
bgneal@330 59
bgneal@330 60 def generate_thumb(self):
gremmie@1 61 if self.thumb:
gremmie@1 62 self.thumb.delete(save=False)
gremmie@1 63
gremmie@1 64 parser = ImageFile.Parser()
gremmie@1 65 for chunk in self.photo.chunks():
gremmie@1 66 parser.feed(chunk)
gremmie@1 67 image = parser.close()
gremmie@1 68 format = image.format
gremmie@1 69 image = scale_image(image)
gremmie@1 70 s = StringIO()
gremmie@1 71 image.save(s, format)
gremmie@1 72 thumb_name = os.path.basename(self.photo.path)
gremmie@1 73 self.thumb.save(thumb_name, ContentFile(s.getvalue()), save=False)
gremmie@1 74
bgneal@491 75 def ogp_tags(self):
bgneal@491 76 """
bgneal@491 77 Returns a dict of Open Graph Protocol meta tags.
bgneal@491 78
bgneal@491 79 """
bgneal@491 80 desc = "Photo of the day: %s." % self.caption
bgneal@491 81 return {
bgneal@491 82 'og:title': self.caption,
bgneal@491 83 'og:type': 'article',
bgneal@491 84 'og:url': self.get_absolute_url(),
bgneal@491 85 'og:image': self.photo.url,
bgneal@491 86 'og:description': desc,
bgneal@491 87 }
bgneal@491 88
gremmie@1 89
gremmie@1 90 class CurrentManager(models.Manager):
bgneal@515 91 """
bgneal@515 92 Manager for the Current model.
bgneal@515 93
bgneal@515 94 """
gremmie@1 95 def get_current_photo(self):
bgneal@515 96 """
bgneal@515 97 Retrieves the current photo object from the current record.
bgneal@515 98
bgneal@515 99 """
gremmie@1 100 try:
gremmie@1 101 c = self.get(pk=1)
gremmie@1 102 return c.potd
gremmie@1 103 except Current.DoesNotExist:
gremmie@1 104 return None
gremmie@1 105
gremmie@1 106 def get_current_id(self):
bgneal@515 107 """
bgneal@515 108 Returns the ID of the current POTD from the current record.
bgneal@515 109
bgneal@515 110 """
gremmie@1 111 potd = self.get_current_photo()
gremmie@1 112 if potd is not None:
gremmie@1 113 return potd.pk
gremmie@1 114 return None
gremmie@1 115
gremmie@1 116
gremmie@1 117 class Current(models.Model):
gremmie@1 118 """This model simply stores the current POTD."""
bgneal@1206 119 potd = models.ForeignKey(Photo, on_delete=models.CASCADE)
gremmie@1 120
gremmie@1 121 objects = CurrentManager()
gremmie@1 122
gremmie@1 123 def __unicode__(self):
gremmie@1 124 return self.potd.__unicode__()
gremmie@1 125
gremmie@1 126 class Meta:
gremmie@1 127 verbose_name_plural = 'Current'
gremmie@1 128
gremmie@1 129
gremmie@1 130 class SequenceManager(models.Manager):
bgneal@515 131 """
bgneal@515 132 Manager for the Sequence model.
bgneal@515 133
bgneal@515 134 """
gremmie@1 135 def insert_photo(self, photo_id):
bgneal@515 136 """
bgneal@515 137 Inserts the given photo_id just after the current photo so it
bgneal@515 138 will appear as tomorrow's POTD.
bgneal@515 139
bgneal@515 140 """
gremmie@1 141 current = Current.objects.get_current_id()
gremmie@1 142 if current is not None:
bgneal@330 143 s = self.get(pk=1)
bgneal@330 144 seq = [int(x) for x in s.seq.split(',')]
bgneal@330 145 if photo_id not in seq:
bgneal@330 146 i = seq.index(current)
bgneal@330 147 seq.insert(i + 1, photo_id)
bgneal@330 148 s.seq = ','.join([str(x) for x in seq])
bgneal@330 149 s.save()
gremmie@1 150
gremmie@1 151 def remove_photo(self, photo_id):
bgneal@515 152 """
bgneal@515 153 Removes a given photo id from the sequence of photos.
bgneal@515 154
bgneal@515 155 """
gremmie@1 156 try:
gremmie@1 157 s = self.get(pk=1)
bgneal@330 158 except Sequence.DoesNotExist:
bgneal@330 159 pass
bgneal@330 160 else:
gremmie@1 161 seq = [int(x) for x in s.seq.split(',')]
gremmie@1 162 if photo_id in seq:
gremmie@1 163 seq.remove(photo_id)
gremmie@1 164 s.seq = ','.join([str(x) for x in seq])
gremmie@1 165 s.save()
gremmie@1 166
gremmie@1 167
gremmie@1 168 class Sequence(models.Model):
gremmie@1 169 """This model stores the sequence of photos for the POTD."""
gremmie@1 170 seq = models.CommaSeparatedIntegerField(max_length=4096)
gremmie@1 171
gremmie@1 172 objects = SequenceManager()
gremmie@1 173
gremmie@1 174 def __unicode__(self):
bgneal@535 175 return u'POTD Sequence %d' % self.id
gremmie@1 176
gremmie@1 177 class Meta:
gremmie@1 178 verbose_name_plural = 'Sequence'