summaryrefslogtreecommitdiff
path: root/feeds.py
diff options
context:
space:
mode:
Diffstat (limited to 'feeds.py')
-rw-r--r--feeds.py99
1 files changed, 44 insertions, 55 deletions
diff --git a/feeds.py b/feeds.py
index bff97cba..65d11684 100644
--- a/feeds.py
+++ b/feeds.py
@@ -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()