diff options
Diffstat (limited to 'feeds.py')
-rw-r--r-- | feeds.py | 99 |
1 files changed, 44 insertions, 55 deletions
@@ -1,57 +1,46 @@ -import datetime -from decimal import Decimal, ROUND_HALF_DOWN +import pytz +from django.contrib.sites.models import Site from django.contrib.syndication.views import Feed -from django.core.cache import cache from django.db.models import Q +from django.utils.feedgenerator import Rss201rev2Feed from django.utils.hashcompat import md5_constructor from django.views.decorators.http import condition +from main.utils import retrieve_latest from main.models import Arch, Repo, Package -from main.utils import CACHE_TIMEOUT, INVALIDATE_TIMEOUT -from main.utils import CACHE_PACKAGE_KEY, CACHE_NEWS_KEY from news.models import News -def utc_offset(): - '''Calculate the UTC offset from local time. Useful for converting values - stored in local time to things like cache last modifed headers.''' - timediff = datetime.datetime.utcnow() - datetime.datetime.now() - secs = timediff.days * 86400 + timediff.seconds - # round to nearest minute - mins = Decimal(secs) / Decimal(60) - mins = mins.quantize(Decimal('0'), rounding=ROUND_HALF_DOWN) - return datetime.timedelta(minutes=int(mins)) - - -def retrieve_package_latest(): - # we could break this down based on the request url, but it would probably - # cost us more in query time to do so. - latest = cache.get(CACHE_PACKAGE_KEY) - if latest: - return latest - try: - latest = Package.objects.values('last_update').latest( - 'last_update')['last_update'] - latest = latest + utc_offset() - # Using add means "don't overwrite anything in there". What could be in - # there is an explicit None value that our refresh signal set, which - # means we want to avoid race condition possibilities for a bit. - cache.add(CACHE_PACKAGE_KEY, latest, CACHE_TIMEOUT) - return latest - except Package.DoesNotExist: - pass - return None +def check_for_unique_id(f): + def wrapper(name, contents=None, attrs=None): + if attrs is None: + attrs = {} + if name == 'guid': + attrs['isPermaLink'] = 'false' + return f(name, contents, attrs) + return wrapper + +class GuidNotPermalinkFeed(Rss201rev2Feed): + def write_items(self, handler): + # Totally disgusting. Monkey-patch the hander so if it sees a + # 'unique-id' field come through, add an isPermalink="false" attribute. + # Workaround for http://code.djangoproject.com/ticket/9800 + handler.addQuickElement = check_for_unique_id(handler.addQuickElement) + super(GuidNotPermalinkFeed, self).write_items(handler) + def package_etag(request, *args, **kwargs): - latest = retrieve_package_latest() + latest = retrieve_latest(Package) if latest: return md5_constructor(str(kwargs) + str(latest)).hexdigest() return None def package_last_modified(request, *args, **kwargs): - return retrieve_package_latest() + return retrieve_latest(Package) class PackageFeed(Feed): + feed_type = GuidNotPermalinkFeed + link = '/packages/' title_template = 'feeds/packages_title.html' description_template = 'feeds/packages_description.html' @@ -97,44 +86,41 @@ class PackageFeed(Feed): s += '.' return s + subtitle = description + def items(self, obj): return obj['qs'] + def item_guid(self, item): + # http://diveintomark.org/archives/2004/05/28/howto-atom-id + date = item.last_update + return 'tag:%s,%s:%s%s' % (Site.objects.get_current().domain, + date.strftime('%Y-%m-%d'), item.get_absolute_url(), + date.strftime('%Y%m%d%H%M')) + def item_pubdate(self, item): - return item.last_update + return item.last_update.replace(tzinfo=pytz.utc) def item_categories(self, item): return (item.repo.name, item.arch.name) -def retrieve_news_latest(): - latest = cache.get(CACHE_NEWS_KEY) - if latest: - return latest - try: - latest = News.objects.values('last_modified').latest( - 'last_modified')['last_modified'] - latest = latest + utc_offset() - # same thoughts apply as in retrieve_package_latest - cache.add(CACHE_NEWS_KEY, latest, CACHE_TIMEOUT) - return latest - except News.DoesNotExist: - pass - return None - def news_etag(request, *args, **kwargs): - latest = retrieve_news_latest() + latest = retrieve_latest(News) if latest: return md5_constructor(str(latest)).hexdigest() return None def news_last_modified(request, *args, **kwargs): - return retrieve_news_latest() + return retrieve_latest(News) class NewsFeed(Feed): + feed_type = GuidNotPermalinkFeed + title = 'Parabola GNU/Linux-libre: Recent news updates' link = '/news/' description = 'The latest news from the Parabola GNU/Linux-libre distribution.' + subtitle = description title_template = 'feeds/news_title.html' description_template = 'feeds/news_description.html' @@ -146,8 +132,11 @@ class NewsFeed(Feed): return News.objects.select_related('author').order_by( '-postdate', '-id')[:10] + def item_guid(self, item): + return item.guid + def item_pubdate(self, item): - return item.postdate + return item.postdate.replace(tzinfo=pytz.utc) def item_author_name(self, item): return item.author.get_full_name() |