qrurls/models.py
author Tero Marttila <terom@paivola.fi>
Wed, 05 Nov 2014 10:26:23 +0100
changeset 88 06ef4789a353
parent 87 88d9c9974d6a
permissions -rw-r--r--
qrurls.models: make URL.apply_publishing_schedule() count optional, to yield an infinite series of publishing times
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
88
06ef4789a353 qrurls.models: make URL.apply_publishing_schedule() count optional, to yield an infinite series of publishing times
Tero Marttila <terom@paivola.fi>
parents: 87
diff changeset
     3
import itertools
80
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
     4
import logging
41
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
     5
import os.path
27
ffcffe3024f1 sane defaults for published in urlitems inline form
Tero Marttila <terom@fixme.fi>
parents: 23
diff changeset
     6
41
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
     7
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
     8
import django.utils.http
83
35bdf2acbbaa invalidate URL cache on URLItem save
Tero Marttila <terom@fixme.fi>
parents: 82
diff changeset
     9
from django import dispatch
4
d56f48f6c94b URL: show qrcode for URL in admin (using google charts)
Tero Marttila <terom@fixme.fi>
parents: 3
diff changeset
    10
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
    11
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
    12
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
    13
from django.db import models
6
e821a59bf3a7 show published state for url items
Tero Marttila <terom@fixme.fi>
parents: 4
diff changeset
    14
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
    15
80
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
    16
log = logging.getLogger('qrurls.models')
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
    17
18
dd08de6f1fe3 user high error correction rate for qrcode
Tero Marttila <terom@fixme.fi>
parents: 17
diff changeset
    18
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
    19
IMAGES_MEDIA = 'qrurls-images'
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
class SecretFileSystemStorage (django.core.files.storage.FileSystemStorage) :
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
        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
    24
    """
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
    HASH = hashlib.sha1
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
    27
    
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
    28
    def _hash (self, content) :
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
    29
        """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
    30
        hash = self.HASH()
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
    31
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
    32
        for chunk in content.chunks() :
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
    33
            hash.update(chunk)
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
        return hash.hexdigest()
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
    36
    
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
    37
    def save (self, name, content) :
66
8ca335eab457 store filename for URLImages
Tero Marttila <terom@fixme.fi>
parents: 63
diff changeset
    38
        """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
    39
        if name is None:
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
    40
            name = content.name
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
    41
        
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
    42
        dirname, filename = os.path.split(name)
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
    43
        basename, fileext = os.path.splitext(filename)
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
    44
        
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
    45
        # hash
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
    46
        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
    47
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
    48
        return super(SecretFileSystemStorage, self).save(name, content)
0
1fc671165892 django startproject/app skeleton
Tero Marttila <terom@paivola.fi>
parents:
diff changeset
    49
2
e838dda048a6 qrurls: basic functionality
Tero Marttila <terom@fixme.fi>
parents: 0
diff changeset
    50
class URL(models.Model):
48
5df9ed6b5976 helptext for shorturl
Tero Marttila <terom@fixme.fi>
parents: 47
diff changeset
    51
    shorturl = models.SlugField(unique=True,
5df9ed6b5976 helptext for shorturl
Tero Marttila <terom@fixme.fi>
parents: 47
diff changeset
    52
            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
    53
    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
    54
            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
    55
    publishing_days = models.IntegerField(default=1,
9d1184cdbd16 make URLFeed publishing_offset user-defineable in days
Tero Marttila <terom@fixme.fi>
parents: 56
diff changeset
    56
            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
    57
    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
    58
            help_text="Text to display together with images.")
2
e838dda048a6 qrurls: basic functionality
Tero Marttila <terom@fixme.fi>
parents: 0
diff changeset
    59
3
e7d3f1a28b24 touchup admin ui
Tero Marttila <terom@fixme.fi>
parents: 2
diff changeset
    60
    class Meta:
12
7605af83cb14 add qrurls index
Tero Marttila <terom@fixme.fi>
parents: 10
diff changeset
    61
        verbose_name = u"URL Feed"
7605af83cb14 add qrurls index
Tero Marttila <terom@fixme.fi>
parents: 10
diff changeset
    62
        verbose_name_plural = u"URL Feeds"
3
e7d3f1a28b24 touchup admin ui
Tero Marttila <terom@fixme.fi>
parents: 2
diff changeset
    63
83
35bdf2acbbaa invalidate URL cache on URLItem save
Tero Marttila <terom@fixme.fi>
parents: 82
diff changeset
    64
    @classmethod
35bdf2acbbaa invalidate URL cache on URLItem save
Tero Marttila <terom@fixme.fi>
parents: 82
diff changeset
    65
    def cache_key (self, shorturl) :
35bdf2acbbaa invalidate URL cache on URLItem save
Tero Marttila <terom@fixme.fi>
parents: 82
diff changeset
    66
        return 'qrurls/url/{shorturl}'.format(shorturl=shorturl)
35bdf2acbbaa invalidate URL cache on URLItem save
Tero Marttila <terom@fixme.fi>
parents: 82
diff changeset
    67
87
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    68
    @classmethod
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    69
    def get_url (cls, shorturl) :
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    70
        """
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    71
            Return the current URL for a given shorturl, from cache or DB.
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    72
            
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    73
            Returns url:str, modified:datetime
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    74
            Raises URLItem.DoesNotExist
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    75
        """
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    76
        key = cls.cache_key(shorturl)
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    77
        get = cache.get(key)
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    78
        
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    79
        if get :
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    80
            log.debug("get cache: %s", key)
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    81
            return get
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    82
        else:
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    83
            # from db
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    84
            url_item = URLItem.get(shorturl=shorturl)
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    85
            set = (
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    86
                url_item.get_absolute_url(),
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    87
                url_item.last_modified()
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    88
            )
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    89
            
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    90
            log.debug("set cache: %s", key)
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    91
            cache.set(key, set)
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    92
            return set
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    93
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
    94
4
d56f48f6c94b URL: show qrcode for URL in admin (using google charts)
Tero Marttila <terom@fixme.fi>
parents: 3
diff changeset
    95
    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
    96
        return QRCODE_API.format(
d56f48f6c94b URL: show qrcode for URL in admin (using google charts)
Tero Marttila <terom@fixme.fi>
parents: 3
diff changeset
    97
                width=size, height=size,
d56f48f6c94b URL: show qrcode for URL in admin (using google charts)
Tero Marttila <terom@fixme.fi>
parents: 3
diff changeset
    98
                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
    99
        )
d56f48f6c94b URL: show qrcode for URL in admin (using google charts)
Tero Marttila <terom@fixme.fi>
parents: 3
diff changeset
   100
d56f48f6c94b URL: show qrcode for URL in admin (using google charts)
Tero Marttila <terom@fixme.fi>
parents: 3
diff changeset
   101
    def qrcode_url (self) :
22
28a72692b749 keep shorturl case sensitive, but warn if not uppercase
Tero Marttila <terom@paivola.fi>
parents: 21
diff changeset
   102
        return 'HTTP://{domain}{url}'.format(
28a72692b749 keep shorturl case sensitive, but warn if not uppercase
Tero Marttila <terom@paivola.fi>
parents: 21
diff changeset
   103
                domain = get_current_site(None).domain.upper(),
23
f9eadb627bb4 simplify urls
Tero Marttila <terom@paivola.fi>
parents: 22
diff changeset
   104
                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
   105
        )
4
d56f48f6c94b URL: show qrcode for URL in admin (using google charts)
Tero Marttila <terom@fixme.fi>
parents: 3
diff changeset
   106
2
e838dda048a6 qrurls: basic functionality
Tero Marttila <terom@fixme.fi>
parents: 0
diff changeset
   107
    def get_absolute_url (self) :
e838dda048a6 qrurls: basic functionality
Tero Marttila <terom@fixme.fi>
parents: 0
diff changeset
   108
        return reverse('shorturl', args=[self.shorturl])
e838dda048a6 qrurls: basic functionality
Tero Marttila <terom@fixme.fi>
parents: 0
diff changeset
   109
47
35a8e63648c8 clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents: 45
diff changeset
   110
    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
   111
        """
35a8e63648c8 clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents: 45
diff changeset
   112
            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
   113
35a8e63648c8 clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents: 45
diff changeset
   114
            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
   115
            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
   116
        """
35a8e63648c8 clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents: 45
diff changeset
   117
        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
   118
            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
   119
        else :
35a8e63648c8 clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents: 45
diff changeset
   120
            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
   121
    
35a8e63648c8 clarify timezones used for URLItem.published, but no actual explicit per-URLFeed timezone..
Tero Marttila <terom@fixme.fi>
parents: 45
diff changeset
   122
    def active_item (self, now=None) :
7
8202196630d3 better reporting of active/upcoming items
Tero Marttila <terom@fixme.fi>
parents: 6
diff changeset
   123
        """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
   124
        now = self.now(now)
6
e821a59bf3a7 show published state for url items
Tero Marttila <terom@fixme.fi>
parents: 4
diff changeset
   125
16
523b3e9eddfa fixbug modelget item upcoming
Tero Marttila <terom@fixme.fi>
parents: 12
diff changeset
   126
        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
   127
            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
   128
        except IndexError :
523b3e9eddfa fixbug modelget item upcoming
Tero Marttila <terom@fixme.fi>
parents: 12
diff changeset
   129
            return None
6
e821a59bf3a7 show published state for url items
Tero Marttila <terom@fixme.fi>
parents: 4
diff changeset
   130
27
ffcffe3024f1 sane defaults for published in urlitems inline form
Tero Marttila <terom@fixme.fi>
parents: 23
diff changeset
   131
    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
   132
        """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
   133
        now = self.now(now)
7
8202196630d3 better reporting of active/upcoming items
Tero Marttila <terom@fixme.fi>
parents: 6
diff changeset
   134
16
523b3e9eddfa fixbug modelget item upcoming
Tero Marttila <terom@fixme.fi>
parents: 12
diff changeset
   135
        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
   136
            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
   137
        except IndexError :
523b3e9eddfa fixbug modelget item upcoming
Tero Marttila <terom@fixme.fi>
parents: 12
diff changeset
   138
            return None
7
8202196630d3 better reporting of active/upcoming items
Tero Marttila <terom@fixme.fi>
parents: 6
diff changeset
   139
27
ffcffe3024f1 sane defaults for published in urlitems inline form
Tero Marttila <terom@fixme.fi>
parents: 23
diff changeset
   140
    def last_item (self) :
ffcffe3024f1 sane defaults for published in urlitems inline form
Tero Marttila <terom@fixme.fi>
parents: 23
diff changeset
   141
        """The last URLItem available."""
ffcffe3024f1 sane defaults for published in urlitems inline form
Tero Marttila <terom@fixme.fi>
parents: 23
diff changeset
   142
ffcffe3024f1 sane defaults for published in urlitems inline form
Tero Marttila <terom@fixme.fi>
parents: 23
diff changeset
   143
        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
   144
            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
   145
        except IndexError :
ffcffe3024f1 sane defaults for published in urlitems inline form
Tero Marttila <terom@fixme.fi>
parents: 23
diff changeset
   146
            return None
ffcffe3024f1 sane defaults for published in urlitems inline form
Tero Marttila <terom@fixme.fi>
parents: 23
diff changeset
   147
56
96e1c616a955 move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents: 51
diff changeset
   148
    @property
96e1c616a955 move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents: 51
diff changeset
   149
    def publishing_timetz (self) :
96e1c616a955 move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents: 51
diff changeset
   150
        """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
   151
        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
   152
    
63
9d1184cdbd16 make URLFeed publishing_offset user-defineable in days
Tero Marttila <terom@fixme.fi>
parents: 56
diff changeset
   153
    @property
9d1184cdbd16 make URLFeed publishing_offset user-defineable in days
Tero Marttila <terom@fixme.fi>
parents: 56
diff changeset
   154
    def publishing_offset (self) :
9d1184cdbd16 make URLFeed publishing_offset user-defineable in days
Tero Marttila <terom@fixme.fi>
parents: 56
diff changeset
   155
        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
   156
96e1c616a955 move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents: 51
diff changeset
   157
    def publishing_schedule (self) :
96e1c616a955 move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents: 51
diff changeset
   158
        """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
   159
96e1c616a955 move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents: 51
diff changeset
   160
        # 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
   161
        item = self.last_item()
96e1c616a955 move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents: 51
diff changeset
   162
96e1c616a955 move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents: 51
diff changeset
   163
        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
   164
            # starting from the following day
96e1c616a955 move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents: 51
diff changeset
   165
            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
   166
        else :
96e1c616a955 move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents: 51
diff changeset
   167
            # defaults to today
96e1c616a955 move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents: 51
diff changeset
   168
            date = self.now().date()
96e1c616a955 move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents: 51
diff changeset
   169
        
96e1c616a955 move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents: 51
diff changeset
   170
        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
   171
    
96e1c616a955 move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents: 51
diff changeset
   172
    @classmethod
88
06ef4789a353 qrurls.models: make URL.apply_publishing_schedule() count optional, to yield an infinite series of publishing times
Tero Marttila <terom@paivola.fi>
parents: 87
diff changeset
   173
    def apply_publishing_schedule (self, date, time, offset, count=None) :
06ef4789a353 qrurls.models: make URL.apply_publishing_schedule() count optional, to yield an infinite series of publishing times
Tero Marttila <terom@paivola.fi>
parents: 87
diff changeset
   174
        """
06ef4789a353 qrurls.models: make URL.apply_publishing_schedule() count optional, to yield an infinite series of publishing times
Tero Marttila <terom@paivola.fi>
parents: 87
diff changeset
   175
            Yield publishing times off given date/time to offset * count.
06ef4789a353 qrurls.models: make URL.apply_publishing_schedule() count optional, to yield an infinite series of publishing times
Tero Marttila <terom@paivola.fi>
parents: 87
diff changeset
   176
06ef4789a353 qrurls.models: make URL.apply_publishing_schedule() count optional, to yield an infinite series of publishing times
Tero Marttila <terom@paivola.fi>
parents: 87
diff changeset
   177
            If count is not given, yields an infinite series of publish-datetimes.
06ef4789a353 qrurls.models: make URL.apply_publishing_schedule() count optional, to yield an infinite series of publishing times
Tero Marttila <terom@paivola.fi>
parents: 87
diff changeset
   178
        """
06ef4789a353 qrurls.models: make URL.apply_publishing_schedule() count optional, to yield an infinite series of publishing times
Tero Marttila <terom@paivola.fi>
parents: 87
diff changeset
   179
06ef4789a353 qrurls.models: make URL.apply_publishing_schedule() count optional, to yield an infinite series of publishing times
Tero Marttila <terom@paivola.fi>
parents: 87
diff changeset
   180
        if count:
06ef4789a353 qrurls.models: make URL.apply_publishing_schedule() count optional, to yield an infinite series of publishing times
Tero Marttila <terom@paivola.fi>
parents: 87
diff changeset
   181
            iter = xrange(count)
06ef4789a353 qrurls.models: make URL.apply_publishing_schedule() count optional, to yield an infinite series of publishing times
Tero Marttila <terom@paivola.fi>
parents: 87
diff changeset
   182
        else:
06ef4789a353 qrurls.models: make URL.apply_publishing_schedule() count optional, to yield an infinite series of publishing times
Tero Marttila <terom@paivola.fi>
parents: 87
diff changeset
   183
            iter = itertools.count()
06ef4789a353 qrurls.models: make URL.apply_publishing_schedule() count optional, to yield an infinite series of publishing times
Tero Marttila <terom@paivola.fi>
parents: 87
diff changeset
   184
06ef4789a353 qrurls.models: make URL.apply_publishing_schedule() count optional, to yield an infinite series of publishing times
Tero Marttila <terom@paivola.fi>
parents: 87
diff changeset
   185
        for index in iter:
56
96e1c616a955 move publishing schedule to URL model, make timetz aware
Tero Marttila <terom@fixme.fi>
parents: 51
diff changeset
   186
            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
   187
2
e838dda048a6 qrurls: basic functionality
Tero Marttila <terom@fixme.fi>
parents: 0
diff changeset
   188
    def __unicode__ (self) :
e838dda048a6 qrurls: basic functionality
Tero Marttila <terom@fixme.fi>
parents: 0
diff changeset
   189
        return self.shorturl
e838dda048a6 qrurls: basic functionality
Tero Marttila <terom@fixme.fi>
parents: 0
diff changeset
   190
28
d1733c82c278 migration for previous commit
Tero Marttila <terom@fixme.fi>
parents: 27
diff changeset
   191
class URLImage(models.Model):
41
4d38296d58a3 use sha1 names for image storage
Tero Marttila <terom@fixme.fi>
parents: 40
diff changeset
   192
    image = models.ImageField(upload_to=IMAGES_MEDIA, storage=SecretFileSystemStorage())
66
8ca335eab457 store filename for URLImages
Tero Marttila <terom@fixme.fi>
parents: 63
diff changeset
   193
    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
   194
    title = models.CharField(max_length=1024, blank=True)
30
d0f56303d8de URLImage
Tero Marttila <terom@fixme.fi>
parents: 28
diff changeset
   195
    uploaded = models.DateTimeField(auto_now_add=True)
d0f56303d8de URLImage
Tero Marttila <terom@fixme.fi>
parents: 28
diff changeset
   196
d0f56303d8de URLImage
Tero Marttila <terom@fixme.fi>
parents: 28
diff changeset
   197
    class Meta:
d0f56303d8de URLImage
Tero Marttila <terom@fixme.fi>
parents: 28
diff changeset
   198
        verbose_name = u"URL Image"
d0f56303d8de URLImage
Tero Marttila <terom@fixme.fi>
parents: 28
diff changeset
   199
        verbose_name_plural = u"URL Images"
d0f56303d8de URLImage
Tero Marttila <terom@fixme.fi>
parents: 28
diff changeset
   200
        ordering = ['uploaded']
d0f56303d8de URLImage
Tero Marttila <terom@fixme.fi>
parents: 28
diff changeset
   201
66
8ca335eab457 store filename for URLImages
Tero Marttila <terom@fixme.fi>
parents: 63
diff changeset
   202
    def save (self) :
8ca335eab457 store filename for URLImages
Tero Marttila <terom@fixme.fi>
parents: 63
diff changeset
   203
        # 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
   204
        # 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
   205
        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
   206
            self.name = self.image.name
66
8ca335eab457 store filename for URLImages
Tero Marttila <terom@fixme.fi>
parents: 63
diff changeset
   207
8ca335eab457 store filename for URLImages
Tero Marttila <terom@fixme.fi>
parents: 63
diff changeset
   208
        super(URLImage, self).save()
8ca335eab457 store filename for URLImages
Tero Marttila <terom@fixme.fi>
parents: 63
diff changeset
   209
32
82eae853e240 tie in URLImage to URLItem
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   210
    def get_absolute_url (self) :
82eae853e240 tie in URLImage to URLItem
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   211
        return self.image.url
82eae853e240 tie in URLImage to URLItem
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   212
30
d0f56303d8de URLImage
Tero Marttila <terom@fixme.fi>
parents: 28
diff changeset
   213
    def __unicode__ (self) :
66
8ca335eab457 store filename for URLImages
Tero Marttila <terom@fixme.fi>
parents: 63
diff changeset
   214
        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
   215
2
e838dda048a6 qrurls: basic functionality
Tero Marttila <terom@fixme.fi>
parents: 0
diff changeset
   216
class URLItem(models.Model):
e838dda048a6 qrurls: basic functionality
Tero Marttila <terom@fixme.fi>
parents: 0
diff changeset
   217
    shorturl = models.ForeignKey(URL)
68
182ac4b328ec add index on URLItem.published
Tero Marttila <terom@fixme.fi>
parents: 66
diff changeset
   218
    published = models.DateTimeField(db_index=True) # UTC
32
82eae853e240 tie in URLImage to URLItem
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   219
82eae853e240 tie in URLImage to URLItem
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   220
    # either-or
82eae853e240 tie in URLImage to URLItem
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   221
    url = models.URLField(blank=True) # populated from image
82eae853e240 tie in URLImage to URLItem
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   222
    image = models.ForeignKey(URLImage, null=True, blank=True)
2
e838dda048a6 qrurls: basic functionality
Tero Marttila <terom@fixme.fi>
parents: 0
diff changeset
   223
    
3
e7d3f1a28b24 touchup admin ui
Tero Marttila <terom@fixme.fi>
parents: 2
diff changeset
   224
    class Meta:
e7d3f1a28b24 touchup admin ui
Tero Marttila <terom@fixme.fi>
parents: 2
diff changeset
   225
        verbose_name = u"URL Item"
e7d3f1a28b24 touchup admin ui
Tero Marttila <terom@fixme.fi>
parents: 2
diff changeset
   226
        verbose_name_plural = u"URL Items"
e7d3f1a28b24 touchup admin ui
Tero Marttila <terom@fixme.fi>
parents: 2
diff changeset
   227
        ordering = ['published']
e7d3f1a28b24 touchup admin ui
Tero Marttila <terom@fixme.fi>
parents: 2
diff changeset
   228
80
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   229
    @classmethod
86
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   230
    def get (cls, shorturl, item_id=None, related=()) :
80
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   231
        """
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   232
            Return the URLItem for a given shorturl, either the given specific one,
87
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
   233
            or the latest, from the database in one SQL query.
80
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   234
87
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
   235
            Raises URLItem.DoesNotExist
80
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   236
        """
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   237
        # JOIN against shorturl, urlimage
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   238
        url_item = cls.objects.select_related(*related)
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   239
81
3a2fdc820c41 drop separate shorturl_id= lookup key, match shorturl.isdigit()
Tero Marttila <terom@fixme.fi>
parents: 80
diff changeset
   240
        if not shorturl:
3a2fdc820c41 drop separate shorturl_id= lookup key, match shorturl.isdigit()
Tero Marttila <terom@fixme.fi>
parents: 80
diff changeset
   241
            raise cls.DoesNotExist()
3a2fdc820c41 drop separate shorturl_id= lookup key, match shorturl.isdigit()
Tero Marttila <terom@fixme.fi>
parents: 80
diff changeset
   242
        elif shorturl.isdigit():
3a2fdc820c41 drop separate shorturl_id= lookup key, match shorturl.isdigit()
Tero Marttila <terom@fixme.fi>
parents: 80
diff changeset
   243
            shorturl_id = int(shorturl)
80
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   244
            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
   245
        else:
81
3a2fdc820c41 drop separate shorturl_id= lookup key, match shorturl.isdigit()
Tero Marttila <terom@fixme.fi>
parents: 80
diff changeset
   246
            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
   247
        
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   248
        # match for published items
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   249
        now = timezone.now()
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   250
        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
   251
       
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   252
        if item_id :
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   253
            # 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
   254
            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
   255
6442e5c97b48 move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents: 81
diff changeset
   256
            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
   257
        else :
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   258
            # most recent
82
6442e5c97b48 move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents: 81
diff changeset
   259
            log.debug("search @ %s", now)
80
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   260
            try:
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   261
                return url_item[0]
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   262
            except IndexError:
85
adddd20cec75 fix DoesNotExist 404 for urlfeed
Tero Marttila <terom@fixme.fi>
parents: 83
diff changeset
   263
                raise cls.DoesNotExist()
80
3aaac91a6654 move URLItem lookup to models URLItem.search()
Tero Marttila <terom@fixme.fi>
parents: 78
diff changeset
   264
82
6442e5c97b48 move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents: 81
diff changeset
   265
    @classmethod
87
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
   266
    def cache_key (cls, shorturl, item_id) :
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
   267
        return 'qrurls/url/{shorturl}/{item}'.format(shorturl=shorturl, item=item_id)
82
6442e5c97b48 move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents: 81
diff changeset
   268
86
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   269
    @classmethod
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   270
    def get_item (cls, shorturl, item_id) :
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   271
        """
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   272
            Return a data dict for the given URLItem, from cache or DB.
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   273
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   274
            Returns { url: str, title: str, image: str, last_modified: datetime }
87
88d9c9974d6a move get_url to URL
Tero Marttila <terom@fixme.fi>
parents: 86
diff changeset
   275
            Raises URLItem.DoesNotExist
86
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   276
        """
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   277
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   278
        key = cls.cache_key(shorturl, item_id)
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   279
        get = cache.get(key)
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   280
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   281
        if get:
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   282
            log.debug("cache get: %s", key)
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   283
            return get
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   284
        else:
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   285
            url_item = URLItem.get(shorturl, item_id=item_id,
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   286
                related=('shorturl', 'image'),
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   287
            )
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   288
            set = dict(
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   289
                    url             = url_item.url,
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   290
                    title           = url_item.title(),
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   291
                    image           = url_item.image.get_absolute_url() if url_item.image else None,
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   292
                    last_modified   = url_item.last_modified(),
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   293
            )
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   294
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   295
            log.debug("cache set: %s: %s", key, set)
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   296
            cache.set(key, set)
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   297
            return set
82
6442e5c97b48 move cache to models URLItem.get_url(), fix image view
Tero Marttila <terom@fixme.fi>
parents: 81
diff changeset
   298
2
e838dda048a6 qrurls: basic functionality
Tero Marttila <terom@fixme.fi>
parents: 0
diff changeset
   299
    def get_absolute_url (self) :
43
3b1f1a928283 rename qrurls image view to item view
Tero Marttila <terom@fixme.fi>
parents: 41
diff changeset
   300
        if self.url :
3b1f1a928283 rename qrurls image view to item view
Tero Marttila <terom@fixme.fi>
parents: 41
diff changeset
   301
            return self.url
44
bbfd0adb2bc3 fix URLItem get_absolute_url() when deleting (\!)
terom
parents: 43
diff changeset
   302
        elif self.shorturl and self.id :
bbfd0adb2bc3 fix URLItem get_absolute_url() when deleting (\!)
terom
parents: 43
diff changeset
   303
            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
   304
        else :
44
bbfd0adb2bc3 fix URLItem get_absolute_url() when deleting (\!)
terom
parents: 43
diff changeset
   305
            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
   306
   
7
8202196630d3 better reporting of active/upcoming items
Tero Marttila <terom@fixme.fi>
parents: 6
diff changeset
   307
    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
   308
        now = self.shorturl.now() # UTC
6
e821a59bf3a7 show published state for url items
Tero Marttila <terom@fixme.fi>
parents: 4
diff changeset
   309
e821a59bf3a7 show published state for url items
Tero Marttila <terom@fixme.fi>
parents: 4
diff changeset
   310
        if now > self.published:
e821a59bf3a7 show published state for url items
Tero Marttila <terom@fixme.fi>
parents: 4
diff changeset
   311
            td = now - self.published
e821a59bf3a7 show published state for url items
Tero Marttila <terom@fixme.fi>
parents: 4
diff changeset
   312
        else :
e821a59bf3a7 show published state for url items
Tero Marttila <terom@fixme.fi>
parents: 4
diff changeset
   313
            td = self.published - now
e821a59bf3a7 show published state for url items
Tero Marttila <terom@fixme.fi>
parents: 4
diff changeset
   314
e821a59bf3a7 show published state for url items
Tero Marttila <terom@fixme.fi>
parents: 4
diff changeset
   315
        days, seconds = td.days, td.seconds
e821a59bf3a7 show published state for url items
Tero Marttila <terom@fixme.fi>
parents: 4
diff changeset
   316
        m, s = divmod(seconds, 60)
e821a59bf3a7 show published state for url items
Tero Marttila <terom@fixme.fi>
parents: 4
diff changeset
   317
        h, m = divmod(m, 60)
7
8202196630d3 better reporting of active/upcoming items
Tero Marttila <terom@fixme.fi>
parents: 6
diff changeset
   318
9
ccb1736fba1a consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents: 7
diff changeset
   319
        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
   320
8202196630d3 better reporting of active/upcoming items
Tero Marttila <terom@fixme.fi>
parents: 6
diff changeset
   321
    def published_state (self) :
9
ccb1736fba1a consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents: 7
diff changeset
   322
        date = self.published.strftime("%Y-%m-%d")
ccb1736fba1a consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents: 7
diff changeset
   323
        published, days, age = self.published_age()
6
e821a59bf3a7 show published state for url items
Tero Marttila <terom@fixme.fi>
parents: 4
diff changeset
   324
9
ccb1736fba1a consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents: 7
diff changeset
   325
        if published and days :
ccb1736fba1a consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents: 7
diff changeset
   326
            return "[{date}]".format(date=date)
ccb1736fba1a consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents: 7
diff changeset
   327
        elif published :
ccb1736fba1a consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents: 7
diff changeset
   328
            return "[{age}]".format(age=age)
6
e821a59bf3a7 show published state for url items
Tero Marttila <terom@fixme.fi>
parents: 4
diff changeset
   329
        elif days :
9
ccb1736fba1a consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents: 7
diff changeset
   330
            return "({when})".format(when=date)
6
e821a59bf3a7 show published state for url items
Tero Marttila <terom@fixme.fi>
parents: 4
diff changeset
   331
        else :
9
ccb1736fba1a consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents: 7
diff changeset
   332
            return "({age})".format(age=age)
6
e821a59bf3a7 show published state for url items
Tero Marttila <terom@fixme.fi>
parents: 4
diff changeset
   333
72
ea7a5a5ce7d4 add Last-Modified to urlitem responses (redirect and html)
Tero Marttila <terom@fixme.fi>
parents: 69
diff changeset
   334
    def last_modified (self) :
ea7a5a5ce7d4 add Last-Modified to urlitem responses (redirect and html)
Tero Marttila <terom@fixme.fi>
parents: 69
diff changeset
   335
        # 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
   336
        return self.published
ea7a5a5ce7d4 add Last-Modified to urlitem responses (redirect and html)
Tero Marttila <terom@fixme.fi>
parents: 69
diff changeset
   337
78
7e40b1d2be3e move urlitem title logic to URLItem.title()
Tero Marttila <terom@fixme.fi>
parents: 77
diff changeset
   338
    def title (self) :
7e40b1d2be3e move urlitem title logic to URLItem.title()
Tero Marttila <terom@fixme.fi>
parents: 77
diff changeset
   339
        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
   340
            return self.image.title
7e40b1d2be3e move urlitem title logic to URLItem.title()
Tero Marttila <terom@fixme.fi>
parents: 77
diff changeset
   341
        else :
7e40b1d2be3e move urlitem title logic to URLItem.title()
Tero Marttila <terom@fixme.fi>
parents: 77
diff changeset
   342
            return self.shorturl.title
7e40b1d2be3e move urlitem title logic to URLItem.title()
Tero Marttila <terom@fixme.fi>
parents: 77
diff changeset
   343
    
2
e838dda048a6 qrurls: basic functionality
Tero Marttila <terom@fixme.fi>
parents: 0
diff changeset
   344
    def __unicode__ (self) :
9
ccb1736fba1a consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents: 7
diff changeset
   345
        return u"{published_state} {url}".format(
ccb1736fba1a consistent published_state prefix format
Tero Marttila <terom@fixme.fi>
parents: 7
diff changeset
   346
                published_state=self.published_state(),
7
8202196630d3 better reporting of active/upcoming items
Tero Marttila <terom@fixme.fi>
parents: 6
diff changeset
   347
                url=self.get_absolute_url(),
8202196630d3 better reporting of active/upcoming items
Tero Marttila <terom@fixme.fi>
parents: 6
diff changeset
   348
        )
32
82eae853e240 tie in URLImage to URLItem
Tero Marttila <terom@fixme.fi>
parents: 30
diff changeset
   349
83
35bdf2acbbaa invalidate URL cache on URLItem save
Tero Marttila <terom@fixme.fi>
parents: 82
diff changeset
   350
@dispatch.receiver(models.signals.post_save, sender=URLItem)
35bdf2acbbaa invalidate URL cache on URLItem save
Tero Marttila <terom@fixme.fi>
parents: 82
diff changeset
   351
def urlitem_save(instance, **kwargs) :
35bdf2acbbaa invalidate URL cache on URLItem save
Tero Marttila <terom@fixme.fi>
parents: 82
diff changeset
   352
    # invalidate cache
35bdf2acbbaa invalidate URL cache on URLItem save
Tero Marttila <terom@fixme.fi>
parents: 82
diff changeset
   353
    key = URL.cache_key(instance.shorturl.shorturl)
35bdf2acbbaa invalidate URL cache on URLItem save
Tero Marttila <terom@fixme.fi>
parents: 82
diff changeset
   354
    log.info("clear cache: %s: %s", instance, key)
35bdf2acbbaa invalidate URL cache on URLItem save
Tero Marttila <terom@fixme.fi>
parents: 82
diff changeset
   355
    cache.delete(key)
35bdf2acbbaa invalidate URL cache on URLItem save
Tero Marttila <terom@fixme.fi>
parents: 82
diff changeset
   356
86
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   357
    key = URLItem.cache_key(instance.shorturl.shorturl, instance.id)
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   358
    log.info("clear cache: %s: %s", instance, key)
656c8ff72f77 caching for item view
Tero Marttila <terom@fixme.fi>
parents: 85
diff changeset
   359
    cache.delete(key)
83
35bdf2acbbaa invalidate URL cache on URLItem save
Tero Marttila <terom@fixme.fi>
parents: 82
diff changeset
   360