comparison potd/models.py @ 581:ee87ea74d46b

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