evorepo/feeds.py
Dan McGee 5dc5688d97 Improve request handling for feeds that haven't changed
By using the condition decorator (in a slightly odd way because these are
class-based views), we can cut down a lot on the response time for returning
304 status code for feeds that haven't changed. The decorator means we no
longer have to completely render the view to see if we can return a 304
status code.

Signed-off-by: Dan McGee <dan@archlinux.org>
2010-09-14 17:42:12 -05:00

115 lines
3.8 KiB
Python

import datetime
from django.contrib.syndication.views import Feed
from django.db.models import Q
from django.utils.hashcompat import md5_constructor
from django.views.decorators.http import condition
from main.models import Arch, Repo, Package
from news.models import News
def package_etag(request, *args, **kwargs):
latest = Package.objects.latest('last_update')
if latest:
return md5_constructor(
str(kwargs) + str(latest.last_update)).hexdigest()
return None
def package_last_modified(request, *args, **kwargs):
# we could break this down based on the request url, but it would probably
# cost us more in query time to do so.
latest = Package.objects.latest('last_update')
if latest:
return latest.last_update
return None
class PackageFeed(Feed):
link = '/packages/'
title_template = 'feeds/packages_title.html'
description_template = 'feeds/packages_description.html'
def __call__(self, request, *args, **kwargs):
wrapper = condition(etag_func=package_etag, last_modified_func=package_last_modified)
return wrapper(super(PackageFeed, self).__call__)(request, *args, **kwargs)
def get_object(self, request, arch='', repo=''):
obj = dict()
qs = Package.objects.select_related('arch', 'repo').order_by('-last_update')
if arch != '':
# feed for a single arch, also include 'any' packages everywhere
a = Arch.objects.get(name=arch)
qs = qs.filter(Q(arch=a) | Q(arch__agnostic=True))
obj['arch'] = a
if repo != '':
# feed for a single arch AND repo
r = Repo.objects.get(name=repo)
qs = qs.filter(repo=r)
obj['repo'] = r
obj['qs'] = qs[:50]
return obj
def title(self, obj):
s = 'Arch Linux: Recent package updates'
if 'repo' in obj:
s += ' (%s [%s])' % (obj['arch'].name, obj['repo'].name.lower())
elif 'arch' in obj:
s += ' (%s)' % (obj['arch'].name)
return s
def description(self, obj):
s = 'Recently updated packages in the Arch Linux package repositories'
if 'arch' in obj:
s += ' for the \'%s\' architecture' % obj['arch'].name.lower()
if not obj['arch'].agnostic:
s += ' (including \'any\' packages)'
if 'repo' in obj:
s += ' in the [%s] repository' % obj['repo'].name.lower()
s += '.'
return s
def items(self, obj):
return obj['qs']
def item_pubdate(self, item):
return item.last_update
def item_categories(self, item):
return (item.repo.name, item.arch.name)
def news_etag(request, *args, **kwargs):
latest = News.objects.latest('last_modified')
if latest:
return md5_constructor(str(latest.last_modified)).hexdigest()
return None
def news_last_modified(request):
latest = News.objects.latest('last_modified')
if latest:
return latest.last_modified
return None
class NewsFeed(Feed):
title = 'Arch Linux: Recent news updates'
link = '/news/'
description = 'The latest and greatest news from the Arch Linux distribution.'
title_template = 'feeds/news_title.html'
description_template = 'feeds/news_description.html'
def __call__(self, request, *args, **kwargs):
wrapper = condition(etag_func=news_etag, last_modified_func=news_last_modified)
return wrapper(super(NewsFeed, self).__call__)(request, *args, **kwargs)
def items(self):
return News.objects.select_related('author').order_by('-postdate', '-id')[:10]
def item_pubdate(self, item):
d = item.postdate
return datetime.datetime(d.year, d.month, d.day)
def item_author_name(self, item):
return item.author.get_full_name()
# vim: set ts=4 sw=4 et: