author | Tero Marttila <terom@fixme.fi> |
Sat, 07 Sep 2013 15:48:23 +0300 | |
changeset 82 | 6442e5c97b48 |
parent 81 | 3a2fdc820c41 |
child 83 | 35bdf2acbbaa |
permissions | -rw-r--r-- |
27
ffcffe3024f1
sane defaults for published in urlitems inline form
Tero Marttila <terom@fixme.fi>
parents:
23
diff
changeset
|
1 |
import datetime |
41
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
2 |
import hashlib |
80
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
3 |
import logging |
41
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
4 |
import os.path |
27
ffcffe3024f1
sane defaults for published in urlitems inline form
Tero Marttila <terom@fixme.fi>
parents:
23
diff
changeset
|
5 |
|
41
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
6 |
import django.core.files.storage |
4
d56f48f6c94b
URL: show qrcode for URL in admin (using google charts)
Tero Marttila <terom@fixme.fi>
parents:
3
diff
changeset
|
7 |
import django.utils.http |
d56f48f6c94b
URL: show qrcode for URL in admin (using google charts)
Tero Marttila <terom@fixme.fi>
parents:
3
diff
changeset
|
8 |
from django.contrib.sites.models import get_current_site |
82
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
9 |
from django.core.cache import cache |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
10 |
from django.core.urlresolvers import reverse |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
11 |
from django.db import models |
6
e821a59bf3a7
show published state for url items
Tero Marttila <terom@fixme.fi>
parents:
4
diff
changeset
|
12 |
from django.utils import timezone |
4
d56f48f6c94b
URL: show qrcode for URL in admin (using google charts)
Tero Marttila <terom@fixme.fi>
parents:
3
diff
changeset
|
13 |
|
80
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
14 |
log = logging.getLogger('qrurls.models') |
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
15 |
|
18
dd08de6f1fe3
user high error correction rate for qrcode
Tero Marttila <terom@fixme.fi>
parents:
17
diff
changeset
|
16 |
QRCODE_API = 'https://chart.googleapis.com/chart?cht=qr&chs={width}x{height}&chl={url}&chld=H' |
41
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
17 |
IMAGES_MEDIA = 'qrurls-images' |
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
18 |
|
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
19 |
class SecretFileSystemStorage (django.core.files.storage.FileSystemStorage) : |
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
20 |
""" |
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
21 |
Store files named by a sha1 hash of their contents. |
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
22 |
""" |
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
23 |
|
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
24 |
HASH = hashlib.sha1 |
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
25 |
|
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
26 |
def _hash (self, content) : |
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
27 |
"""Compute hash for given UploadedFile (as a hex string).""" |
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
28 |
hash = self.HASH() |
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
29 |
|
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
30 |
for chunk in content.chunks() : |
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
31 |
hash.update(chunk) |
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
32 |
|
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
33 |
return hash.hexdigest() |
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
34 |
|
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
35 |
def save (self, name, content) : |
66 | 36 |
"""Convert uploaded filename to a hash of the contents for storage.""" |
41
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
37 |
if name is None: |
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
38 |
name = content.name |
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
39 |
|
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
40 |
dirname, filename = os.path.split(name) |
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
41 |
basename, fileext = os.path.splitext(filename) |
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
42 |
|
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
43 |
# hash |
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
44 |
name = "%s/%s%s" % (dirname, self._hash(content), fileext) |
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
45 |
|
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
46 |
return super(SecretFileSystemStorage, self).save(name, content) |
0
1fc671165892
django startproject/app skeleton
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
47 |
|
2 | 48 |
class URL(models.Model): |
48 | 49 |
shorturl = models.SlugField(unique=True, |
50 |
help_text="Changing this will break existing QR-codes!") |
|
47
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
51 |
publishing_time = models.TimeField(default=datetime.time(), |
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
52 |
help_text="Default time to publish new URLItems (in timezone)") |
63
9d1184cdbd16
make URLFeed publishing_offset user-defineable in days
Tero Marttila <terom@fixme.fi>
parents:
56
diff
changeset
|
53 |
publishing_days = models.IntegerField(default=1, |
9d1184cdbd16
make URLFeed publishing_offset user-defineable in days
Tero Marttila <terom@fixme.fi>
parents:
56
diff
changeset
|
54 |
help_text="Default interval for publishing new URLItems") |
51
6f35a169ef01
Make URLImage title optional, use URLFeed title
Tero Marttila <terom@fixme.fi>
parents:
48
diff
changeset
|
55 |
title = models.CharField(max_length=1024, blank=True, null=True, |
6f35a169ef01
Make URLImage title optional, use URLFeed title
Tero Marttila <terom@fixme.fi>
parents:
48
diff
changeset
|
56 |
help_text="Text to display together with images.") |
2 | 57 |
|
3 | 58 |
class Meta: |
12 | 59 |
verbose_name = u"URL Feed" |
60 |
verbose_name_plural = u"URL Feeds" |
|
3 | 61 |
|
4
d56f48f6c94b
URL: show qrcode for URL in admin (using google charts)
Tero Marttila <terom@fixme.fi>
parents:
3
diff
changeset
|
62 |
def qrcode_img (self, size=512) : |
d56f48f6c94b
URL: show qrcode for URL in admin (using google charts)
Tero Marttila <terom@fixme.fi>
parents:
3
diff
changeset
|
63 |
return QRCODE_API.format( |
d56f48f6c94b
URL: show qrcode for URL in admin (using google charts)
Tero Marttila <terom@fixme.fi>
parents:
3
diff
changeset
|
64 |
width=size, height=size, |
d56f48f6c94b
URL: show qrcode for URL in admin (using google charts)
Tero Marttila <terom@fixme.fi>
parents:
3
diff
changeset
|
65 |
url=django.utils.http.urlquote(self.qrcode_url()), |
d56f48f6c94b
URL: show qrcode for URL in admin (using google charts)
Tero Marttila <terom@fixme.fi>
parents:
3
diff
changeset
|
66 |
) |
d56f48f6c94b
URL: show qrcode for URL in admin (using google charts)
Tero Marttila <terom@fixme.fi>
parents:
3
diff
changeset
|
67 |
|
d56f48f6c94b
URL: show qrcode for URL in admin (using google charts)
Tero Marttila <terom@fixme.fi>
parents:
3
diff
changeset
|
68 |
def qrcode_url (self) : |
22
28a72692b749
keep shorturl case sensitive, but warn if not uppercase
Tero Marttila <terom@paivola.fi>
parents:
21
diff
changeset
|
69 |
return 'HTTP://{domain}{url}'.format( |
28a72692b749
keep shorturl case sensitive, but warn if not uppercase
Tero Marttila <terom@paivola.fi>
parents:
21
diff
changeset
|
70 |
domain = get_current_site(None).domain.upper(), |
23 | 71 |
url = self.get_absolute_url(), |
22
28a72692b749
keep shorturl case sensitive, but warn if not uppercase
Tero Marttila <terom@paivola.fi>
parents:
21
diff
changeset
|
72 |
) |
4
d56f48f6c94b
URL: show qrcode for URL in admin (using google charts)
Tero Marttila <terom@fixme.fi>
parents:
3
diff
changeset
|
73 |
|
2 | 74 |
def get_absolute_url (self) : |
75 |
return reverse('shorturl', args=[self.shorturl]) |
|
76 |
||
47
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
77 |
def now (self, now=None) : |
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
78 |
""" |
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
79 |
Return database-compatible concept of "now". |
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
80 |
|
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
81 |
All datetimes are strictly stored and compared as UTC. Any |
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
82 |
timezone-aware logic should happen in the admin. |
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
83 |
""" |
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
84 |
if now : |
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
85 |
return now |
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
86 |
else : |
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
87 |
return timezone.now() |
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
88 |
|
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
89 |
def active_item (self, now=None) : |
7
8202196630d3
better reporting of active/upcoming items
Tero Marttila <terom@fixme.fi>
parents:
6
diff
changeset
|
90 |
"""Currently published URLItem.""" |
47
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
91 |
now = self.now(now) |
6
e821a59bf3a7
show published state for url items
Tero Marttila <terom@fixme.fi>
parents:
4
diff
changeset
|
92 |
|
16
523b3e9eddfa
fixbug modelget item upcoming
Tero Marttila <terom@fixme.fi>
parents:
12
diff
changeset
|
93 |
try : |
69
f7db1b752763
URL model: use self.urlitem_set to let orm caching work for item.shorturl (optimize one unneeded query on view)
Tero Marttila <terom@fixme.fi>
parents:
68
diff
changeset
|
94 |
return self.urlitem_set.filter(published__lt=now).order_by('-published')[0] |
16
523b3e9eddfa
fixbug modelget item upcoming
Tero Marttila <terom@fixme.fi>
parents:
12
diff
changeset
|
95 |
except IndexError : |
523b3e9eddfa
fixbug modelget item upcoming
Tero Marttila <terom@fixme.fi>
parents:
12
diff
changeset
|
96 |
return None |
6
e821a59bf3a7
show published state for url items
Tero Marttila <terom@fixme.fi>
parents:
4
diff
changeset
|
97 |
|
27
ffcffe3024f1
sane defaults for published in urlitems inline form
Tero Marttila <terom@fixme.fi>
parents:
23
diff
changeset
|
98 |
def upcoming_item (self, now=None) : |
47
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
99 |
"""Next-up to-be-published URLItem.""" |
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
100 |
now = self.now(now) |
7
8202196630d3
better reporting of active/upcoming items
Tero Marttila <terom@fixme.fi>
parents:
6
diff
changeset
|
101 |
|
16
523b3e9eddfa
fixbug modelget item upcoming
Tero Marttila <terom@fixme.fi>
parents:
12
diff
changeset
|
102 |
try : |
69
f7db1b752763
URL model: use self.urlitem_set to let orm caching work for item.shorturl (optimize one unneeded query on view)
Tero Marttila <terom@fixme.fi>
parents:
68
diff
changeset
|
103 |
return self.urlitem_set.filter(published__gt=now).order_by('published')[0] |
16
523b3e9eddfa
fixbug modelget item upcoming
Tero Marttila <terom@fixme.fi>
parents:
12
diff
changeset
|
104 |
except IndexError : |
523b3e9eddfa
fixbug modelget item upcoming
Tero Marttila <terom@fixme.fi>
parents:
12
diff
changeset
|
105 |
return None |
7
8202196630d3
better reporting of active/upcoming items
Tero Marttila <terom@fixme.fi>
parents:
6
diff
changeset
|
106 |
|
27
ffcffe3024f1
sane defaults for published in urlitems inline form
Tero Marttila <terom@fixme.fi>
parents:
23
diff
changeset
|
107 |
def last_item (self) : |
ffcffe3024f1
sane defaults for published in urlitems inline form
Tero Marttila <terom@fixme.fi>
parents:
23
diff
changeset
|
108 |
"""The last URLItem available.""" |
ffcffe3024f1
sane defaults for published in urlitems inline form
Tero Marttila <terom@fixme.fi>
parents:
23
diff
changeset
|
109 |
|
ffcffe3024f1
sane defaults for published in urlitems inline form
Tero Marttila <terom@fixme.fi>
parents:
23
diff
changeset
|
110 |
try : |
69
f7db1b752763
URL model: use self.urlitem_set to let orm caching work for item.shorturl (optimize one unneeded query on view)
Tero Marttila <terom@fixme.fi>
parents:
68
diff
changeset
|
111 |
return self.urlitem_set.order_by('-published')[0] |
27
ffcffe3024f1
sane defaults for published in urlitems inline form
Tero Marttila <terom@fixme.fi>
parents:
23
diff
changeset
|
112 |
except IndexError : |
ffcffe3024f1
sane defaults for published in urlitems inline form
Tero Marttila <terom@fixme.fi>
parents:
23
diff
changeset
|
113 |
return None |
ffcffe3024f1
sane defaults for published in urlitems inline form
Tero Marttila <terom@fixme.fi>
parents:
23
diff
changeset
|
114 |
|
56
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
115 |
@property |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
116 |
def publishing_timetz (self) : |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
117 |
"""publishing_time, with tzinfo on the correct timezone.""" |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
118 |
return self.publishing_time.replace(tzinfo=timezone.get_current_timezone()) |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
119 |
|
63
9d1184cdbd16
make URLFeed publishing_offset user-defineable in days
Tero Marttila <terom@fixme.fi>
parents:
56
diff
changeset
|
120 |
@property |
9d1184cdbd16
make URLFeed publishing_offset user-defineable in days
Tero Marttila <terom@fixme.fi>
parents:
56
diff
changeset
|
121 |
def publishing_offset (self) : |
9d1184cdbd16
make URLFeed publishing_offset user-defineable in days
Tero Marttila <terom@fixme.fi>
parents:
56
diff
changeset
|
122 |
return datetime.timedelta(days=self.publishing_days) |
56
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
123 |
|
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
124 |
def publishing_schedule (self) : |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
125 |
"""Calculate initial URLItem.published values for feed.""" |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
126 |
|
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
127 |
# following the last item in the queue |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
128 |
item = self.last_item() |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
129 |
|
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
130 |
if item and item.published > self.now(): |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
131 |
# starting from the following day |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
132 |
date = item.published.date() + self.publishing_offset |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
133 |
else : |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
134 |
# defaults to today |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
135 |
date = self.now().date() |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
136 |
|
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
137 |
return date, self.publishing_timetz, self.publishing_offset |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
138 |
|
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
139 |
@classmethod |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
140 |
def apply_publishing_schedule (self, date, time, offset, count) : |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
141 |
"""Yield publishing times off given date/time to offset * count.""" |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
142 |
for index in xrange(0, count) : |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
143 |
yield datetime.datetime.combine(date + offset * index, time) |
96e1c616a955
move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents:
51
diff
changeset
|
144 |
|
2 | 145 |
def __unicode__ (self) : |
146 |
return self.shorturl |
|
147 |
||
28
d1733c82c278
migration for previous commit
Tero Marttila <terom@fixme.fi>
parents:
27
diff
changeset
|
148 |
class URLImage(models.Model): |
41
4d38296d58a3
use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents:
40
diff
changeset
|
149 |
image = models.ImageField(upload_to=IMAGES_MEDIA, storage=SecretFileSystemStorage()) |
66 | 150 |
name = models.CharField(max_length=512, blank=False) |
51
6f35a169ef01
Make URLImage title optional, use URLFeed title
Tero Marttila <terom@fixme.fi>
parents:
48
diff
changeset
|
151 |
title = models.CharField(max_length=1024, blank=True) |
30 | 152 |
uploaded = models.DateTimeField(auto_now_add=True) |
153 |
||
154 |
class Meta: |
|
155 |
verbose_name = u"URL Image" |
|
156 |
verbose_name_plural = u"URL Images" |
|
157 |
ordering = ['uploaded'] |
|
158 |
||
66 | 159 |
def save (self) : |
160 |
# keep real filename before saving with hash |
|
77
40e91c2d4579
fix bug where name would be set to hash when editing a urlimage
Tero Marttila <terom@fixme.fi>
parents:
72
diff
changeset
|
161 |
# but not when updating! |
40e91c2d4579
fix bug where name would be set to hash when editing a urlimage
Tero Marttila <terom@fixme.fi>
parents:
72
diff
changeset
|
162 |
if not self.name: |
40e91c2d4579
fix bug where name would be set to hash when editing a urlimage
Tero Marttila <terom@fixme.fi>
parents:
72
diff
changeset
|
163 |
self.name = self.image.name |
66 | 164 |
|
165 |
super(URLImage, self).save() |
|
166 |
||
32 | 167 |
def get_absolute_url (self) : |
168 |
return self.image.url |
|
169 |
||
30 | 170 |
def __unicode__ (self) : |
66 | 171 |
return "[%s] %s" % (self.uploaded.strftime("%Y-%m-%d"), self.name) |
28
d1733c82c278
migration for previous commit
Tero Marttila <terom@fixme.fi>
parents:
27
diff
changeset
|
172 |
|
2 | 173 |
class URLItem(models.Model): |
174 |
shorturl = models.ForeignKey(URL) |
|
68
182ac4b328ec
add index on URLItem.published
Tero Marttila <terom@fixme.fi>
parents:
66
diff
changeset
|
175 |
published = models.DateTimeField(db_index=True) # UTC |
32 | 176 |
|
177 |
# either-or |
|
178 |
url = models.URLField(blank=True) # populated from image |
|
179 |
image = models.ForeignKey(URLImage, null=True, blank=True) |
|
2 | 180 |
|
3 | 181 |
class Meta: |
182 |
verbose_name = u"URL Item" |
|
183 |
verbose_name_plural = u"URL Items" |
|
184 |
ordering = ['published'] |
|
185 |
||
80
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
186 |
@classmethod |
82
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
187 |
def get_item (cls, shorturl, item_id=None, related=()) : |
80
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
188 |
""" |
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
189 |
Return the URLItem for a given shorturl, either the given specific one, |
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
190 |
or the latest, from the database. |
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
191 |
|
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
192 |
Raises URLItem.NotFound |
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
193 |
""" |
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
194 |
# JOIN against shorturl, urlimage |
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
195 |
url_item = cls.objects.select_related(*related) |
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
196 |
|
81
3a2fdc820c41
drop separate shorturl_id= lookup key, match shorturl.isdigit()
Tero Marttila <terom@fixme.fi>
parents:
80
diff
changeset
|
197 |
if not shorturl: |
3a2fdc820c41
drop separate shorturl_id= lookup key, match shorturl.isdigit()
Tero Marttila <terom@fixme.fi>
parents:
80
diff
changeset
|
198 |
raise cls.DoesNotExist() |
3a2fdc820c41
drop separate shorturl_id= lookup key, match shorturl.isdigit()
Tero Marttila <terom@fixme.fi>
parents:
80
diff
changeset
|
199 |
elif shorturl.isdigit(): |
3a2fdc820c41
drop separate shorturl_id= lookup key, match shorturl.isdigit()
Tero Marttila <terom@fixme.fi>
parents:
80
diff
changeset
|
200 |
shorturl_id = int(shorturl) |
80
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
201 |
url_item = url_item.filter(shorturl__id=shorturl_id) |
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
202 |
else: |
81
3a2fdc820c41
drop separate shorturl_id= lookup key, match shorturl.isdigit()
Tero Marttila <terom@fixme.fi>
parents:
80
diff
changeset
|
203 |
url_item = url_item.filter(shorturl__shorturl=shorturl) |
80
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
204 |
|
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
205 |
# match for published items |
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
206 |
now = timezone.now() |
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
207 |
url_item = url_item.filter(published__lt=now).order_by('-published') |
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
208 |
|
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
209 |
if item_id : |
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
210 |
# specific, but still the published on |
82
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
211 |
item_id = int(item_id) |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
212 |
log.debug("search @ %d", item_id) |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
213 |
|
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
214 |
return url_item.get(id=item_id) # raises DoesNotExist |
80
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
215 |
else : |
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
216 |
# most recent |
82
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
217 |
log.debug("search @ %s", now) |
80
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
218 |
try: |
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
219 |
return url_item[0] |
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
220 |
except IndexError: |
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
221 |
raise DoesNotExist() |
3aaac91a6654
move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents:
78
diff
changeset
|
222 |
|
82
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
223 |
@classmethod |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
224 |
def get_url (cls, shorturl) : |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
225 |
""" |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
226 |
Return the current URL for a given shorturl, from cache or DB. |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
227 |
|
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
228 |
Returns url:str, modified:datetime |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
229 |
Raises URLItem.NotFound |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
230 |
""" |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
231 |
|
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
232 |
key = 'qrurls/url/{shorturl}'.format(shorturl=shorturl) |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
233 |
get = cache.get(key) |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
234 |
|
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
235 |
if get : |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
236 |
url, modified = get |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
237 |
log.debug("get cache: %s: %s", key, url) |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
238 |
else: |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
239 |
# from db |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
240 |
url_item = cls.get_item(shorturl=shorturl) |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
241 |
|
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
242 |
url = url_item.get_absolute_url() |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
243 |
modified = url_item.last_modified() |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
244 |
|
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
245 |
log.debug("set cache: %s: %s", key, url) |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
246 |
cache.set(key, (url, modified)) # XXX: expiry |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
247 |
|
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
248 |
return url, modified |
6442e5c97b48
move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents:
81
diff
changeset
|
249 |
|
2 | 250 |
def get_absolute_url (self) : |
43
3b1f1a928283
rename qrurls image view to item view
Tero Marttila <terom@fixme.fi>
parents:
41
diff
changeset
|
251 |
if self.url : |
3b1f1a928283
rename qrurls image view to item view
Tero Marttila <terom@fixme.fi>
parents:
41
diff
changeset
|
252 |
return self.url |
44 | 253 |
elif self.shorturl and self.id : |
254 |
return reverse('shorturl_item', kwargs=dict(shorturl=self.shorturl, item_id=self.id)) |
|
35
acc1a366fa7c
move URLItem save() override to just get_absolute_url(), since we won't have an item_id at save() time when adding
Tero Marttila <terom@fixme.fi>
parents:
33
diff
changeset
|
255 |
else : |
44 | 256 |
return None |
47
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
257 |
|
7
8202196630d3
better reporting of active/upcoming items
Tero Marttila <terom@fixme.fi>
parents:
6
diff
changeset
|
258 |
def published_age (self) : |
47
35a8e63648c8
clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents:
45
diff
changeset
|
259 |
now = self.shorturl.now() # UTC |
6
e821a59bf3a7
show published state for url items
Tero Marttila <terom@fixme.fi>
parents:
4
diff
changeset
|
260 |
|
e821a59bf3a7
show published state for url items
Tero Marttila <terom@fixme.fi>
parents:
4
diff
changeset
|
261 |
if now > self.published: |
e821a59bf3a7
show published state for url items
Tero Marttila <terom@fixme.fi>
parents:
4
diff
changeset
|
262 |
td = now - self.published |
e821a59bf3a7
show published state for url items
Tero Marttila <terom@fixme.fi>
parents:
4
diff
changeset
|
263 |
else : |
e821a59bf3a7
show published state for url items
Tero Marttila <terom@fixme.fi>
parents:
4
diff
changeset
|
264 |
td = self.published - now |
e821a59bf3a7
show published state for url items
Tero Marttila <terom@fixme.fi>
parents:
4
diff
changeset
|
265 |
|
e821a59bf3a7
show published state for url items
Tero Marttila <terom@fixme.fi>
parents:
4
diff
changeset
|
266 |
days, seconds = td.days, td.seconds |
e821a59bf3a7
show published state for url items
Tero Marttila <terom@fixme.fi>
parents:
4
diff
changeset
|
267 |
m, s = divmod(seconds, 60) |
e821a59bf3a7
show published state for url items
Tero Marttila <terom@fixme.fi>
parents:
4
diff
changeset
|
268 |
h, m = divmod(m, 60) |
7
8202196630d3
better reporting of active/upcoming items
Tero Marttila <terom@fixme.fi>
parents:
6
diff
changeset
|
269 |
|
9
ccb1736fba1a
consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
270 |
return (self.published < now), days, "{h}h {m}m {s}s".format(h=h, m=m, s=s) |
7
8202196630d3
better reporting of active/upcoming items
Tero Marttila <terom@fixme.fi>
parents:
6
diff
changeset
|
271 |
|
8202196630d3
better reporting of active/upcoming items
Tero Marttila <terom@fixme.fi>
parents:
6
diff
changeset
|
272 |
def published_state (self) : |
9
ccb1736fba1a
consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
273 |
date = self.published.strftime("%Y-%m-%d") |
ccb1736fba1a
consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
274 |
published, days, age = self.published_age() |
6
e821a59bf3a7
show published state for url items
Tero Marttila <terom@fixme.fi>
parents:
4
diff
changeset
|
275 |
|
9
ccb1736fba1a
consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
276 |
if published and days : |
ccb1736fba1a
consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
277 |
return "[{date}]".format(date=date) |
ccb1736fba1a
consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
278 |
elif published : |
ccb1736fba1a
consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
279 |
return "[{age}]".format(age=age) |
6
e821a59bf3a7
show published state for url items
Tero Marttila <terom@fixme.fi>
parents:
4
diff
changeset
|
280 |
elif days : |
9
ccb1736fba1a
consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
281 |
return "({when})".format(when=date) |
6
e821a59bf3a7
show published state for url items
Tero Marttila <terom@fixme.fi>
parents:
4
diff
changeset
|
282 |
else : |
9
ccb1736fba1a
consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
283 |
return "({age})".format(age=age) |
6
e821a59bf3a7
show published state for url items
Tero Marttila <terom@fixme.fi>
parents:
4
diff
changeset
|
284 |
|
72
ea7a5a5ce7d4
add Last-Modified to urlitem responses (redirect and html)
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
285 |
def last_modified (self) : |
ea7a5a5ce7d4
add Last-Modified to urlitem responses (redirect and html)
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
286 |
# XXX: this asumes that URLImage is never changed after publishing.. |
ea7a5a5ce7d4
add Last-Modified to urlitem responses (redirect and html)
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
287 |
return self.published |
ea7a5a5ce7d4
add Last-Modified to urlitem responses (redirect and html)
Tero Marttila <terom@fixme.fi>
parents:
69
diff
changeset
|
288 |
|
78
7e40b1d2be3e
move urlitem title logic to URLItem.title()
Tero Marttila <terom@fixme.fi>
parents:
77
diff
changeset
|
289 |
def title (self) : |
7e40b1d2be3e
move urlitem title logic to URLItem.title()
Tero Marttila <terom@fixme.fi>
parents:
77
diff
changeset
|
290 |
if self.image and self.image.title.strip() : |
7e40b1d2be3e
move urlitem title logic to URLItem.title()
Tero Marttila <terom@fixme.fi>
parents:
77
diff
changeset
|
291 |
return self.image.title |
7e40b1d2be3e
move urlitem title logic to URLItem.title()
Tero Marttila <terom@fixme.fi>
parents:
77
diff
changeset
|
292 |
else : |
7e40b1d2be3e
move urlitem title logic to URLItem.title()
Tero Marttila <terom@fixme.fi>
parents:
77
diff
changeset
|
293 |
return self.shorturl.title |
7e40b1d2be3e
move urlitem title logic to URLItem.title()
Tero Marttila <terom@fixme.fi>
parents:
77
diff
changeset
|
294 |
|
2 | 295 |
def __unicode__ (self) : |
9
ccb1736fba1a
consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
296 |
return u"{published_state} {url}".format( |
ccb1736fba1a
consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents:
7
diff
changeset
|
297 |
published_state=self.published_state(), |
7
8202196630d3
better reporting of active/upcoming items
Tero Marttila <terom@fixme.fi>
parents:
6
diff
changeset
|
298 |
url=self.get_absolute_url(), |
8202196630d3
better reporting of active/upcoming items
Tero Marttila <terom@fixme.fi>
parents:
6
diff
changeset
|
299 |
) |
32 | 300 |