1 import datetime |
1 import datetime |
2 import hashlib |
2 import hashlib |
3 import logging |
3 import logging |
4 import os.path |
4 import os.path |
5 |
5 |
6 from django.db import models |
|
7 import django.core.files.storage |
6 import django.core.files.storage |
8 from django.core.urlresolvers import reverse |
|
9 import django.utils.http |
7 import django.utils.http |
10 from django.contrib.sites.models import get_current_site |
8 from django.contrib.sites.models import get_current_site |
|
9 from django.core.cache import cache |
|
10 from django.core.urlresolvers import reverse |
|
11 from django.db import models |
11 from django.utils import timezone |
12 from django.utils import timezone |
12 |
13 |
13 log = logging.getLogger('qrurls.models') |
14 log = logging.getLogger('qrurls.models') |
14 |
15 |
15 QRCODE_API = 'https://chart.googleapis.com/chart?cht=qr&chs={width}x{height}&chl={url}&chld=H' |
16 QRCODE_API = 'https://chart.googleapis.com/chart?cht=qr&chs={width}x{height}&chl={url}&chld=H' |
181 verbose_name = u"URL Item" |
182 verbose_name = u"URL Item" |
182 verbose_name_plural = u"URL Items" |
183 verbose_name_plural = u"URL Items" |
183 ordering = ['published'] |
184 ordering = ['published'] |
184 |
185 |
185 @classmethod |
186 @classmethod |
186 def search (cls, shorturl=None, item_id=None, related=()) : |
187 def get_item (cls, shorturl, item_id=None, related=()) : |
187 """ |
188 """ |
188 Return the URLItem for a given shorturl, either the given specific one, |
189 Return the URLItem for a given shorturl, either the given specific one, |
189 or the latest, from the database. |
190 or the latest, from the database. |
190 |
191 |
191 Raises URLItem.NotFound |
192 Raises URLItem.NotFound |
202 url_item = url_item.filter(shorturl__shorturl=shorturl) |
203 url_item = url_item.filter(shorturl__shorturl=shorturl) |
203 |
204 |
204 # match for published items |
205 # match for published items |
205 now = timezone.now() |
206 now = timezone.now() |
206 url_item = url_item.filter(published__lt=now).order_by('-published') |
207 url_item = url_item.filter(published__lt=now).order_by('-published') |
207 |
|
208 log.info("Search URLItem @ %s", now) |
|
209 |
208 |
210 if item_id : |
209 if item_id : |
211 # specific, but still the published on |
210 # specific, but still the published on |
212 return url_item.get(id=int(item_id)) # raises DoesNotExist |
211 item_id = int(item_id) |
|
212 log.debug("search @ %d", item_id) |
|
213 |
|
214 return url_item.get(id=item_id) # raises DoesNotExist |
213 else : |
215 else : |
214 # most recent |
216 # most recent |
|
217 log.debug("search @ %s", now) |
215 try: |
218 try: |
216 return url_item[0] |
219 return url_item[0] |
217 except IndexError: |
220 except IndexError: |
218 raise DoesNotExist() |
221 raise DoesNotExist() |
|
222 |
|
223 @classmethod |
|
224 def get_url (cls, shorturl) : |
|
225 """ |
|
226 Return the current URL for a given shorturl, from cache or DB. |
|
227 |
|
228 Returns url:str, modified:datetime |
|
229 Raises URLItem.NotFound |
|
230 """ |
|
231 |
|
232 key = 'qrurls/url/{shorturl}'.format(shorturl=shorturl) |
|
233 get = cache.get(key) |
|
234 |
|
235 if get : |
|
236 url, modified = get |
|
237 log.debug("get cache: %s: %s", key, url) |
|
238 else: |
|
239 # from db |
|
240 url_item = cls.get_item(shorturl=shorturl) |
|
241 |
|
242 url = url_item.get_absolute_url() |
|
243 modified = url_item.last_modified() |
|
244 |
|
245 log.debug("set cache: %s: %s", key, url) |
|
246 cache.set(key, (url, modified)) # XXX: expiry |
|
247 |
|
248 return url, modified |
219 |
249 |
220 def get_absolute_url (self) : |
250 def get_absolute_url (self) : |
221 if self.url : |
251 if self.url : |
222 return self.url |
252 return self.url |
223 elif self.shorturl and self.id : |
253 elif self.shorturl and self.id : |