Mercurial > public > sg101
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' |