diff --git a/django/core/rss.py b/django/core/rss.py index 7563d2ea82386..e75d66ab2b03a 100644 --- a/django/core/rss.py +++ b/django/core/rss.py @@ -1,9 +1,90 @@ -from django.core.exceptions import ObjectDoesNotExist -from django.core.template import Context, loader +from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist +from django.core.template import Context, loader, Template, TemplateDoesNotExist from django.models.core import sites from django.utils import feedgenerator from django.conf.settings import LANGUAGE_CODE, SETTINGS_MODULE +def add_domain(domain, url): + if not url.startswith('http://'): + url = u'http://%s%s' % (domain, url) + return url + +class FeedDoesNotExist(ObjectDoesNotExist): + pass + +class Feed: + item_pubdate = None + enclosure_url = None + + def item_link(self, item): + try: + return item.get_absolute_url() + except AttributeError: + raise ImproperlyConfigured, "Give your %s class a get_absolute_url() method, or define an item_link() method in your RSS class." % item.__class__.__name__ + + def __get_dynamic_attr(self, attname, obj): + attr = getattr(self, attname) + if callable(attr): + try: + return attr(obj) + except TypeError: + return attr() + return attr + + def get_feed(self, url=None): + """ + Returns a feedgenerator.DefaultRssFeed object, fully populated, for + this feed. Raises FeedDoesNotExist for invalid parameters. + """ + if url: + try: + obj = self.get_object(url.split('/')) + except (AttributeError, ObjectDoesNotExist): + raise FeedDoesNotExist + else: + obj = None + + current_site = sites.get_current() + link = self.__get_dynamic_attr('link', obj) + link = add_domain(current_site.domain, link) + + feed = feedgenerator.DefaultRssFeed( + title = self.__get_dynamic_attr('title', obj), + link = link, + description = self.__get_dynamic_attr('description', obj), + language = LANGUAGE_CODE.decode() + ) + + try: + title_template = loader.get_template('rss/%s_title' % self.slug) + except TemplateDoesNotExist: + title_template = Template('{{ obj }}') + try: + description_template = loader.get_template('rss/%s_description' % self.slug) + except TemplateDoesNotExist: + description_template = Template('{{ obj }}') + + for item in self.__get_dynamic_attr('items', obj): + link = add_domain(current_site.domain, self.__get_dynamic_attr('item_link', item)) + enc = None + enc_url = self.__get_dynamic_attr('enclosure_url', item) + if enc_url: + enc = feedgenerator.Enclosure( + url = enc_url.decode('utf-8'), + length = str(self.__get_dynamic_attr('enclosure_length', item)).decode('utf-8'), + mime_type = self.__get_dynamic_attr('enclosure_mime_type', item).decode('utf-8'), + ) + feed.add_item( + title = title_template.render(Context({'obj': item, 'site': current_site})).decode('utf-8'), + link = link, + description = description_template.render(Context({'obj': item, 'site': current_site})).decode('utf-8'), + unique_id = link, + enclosure = enc, + pubdate = self.__get_dynamic_attr('item_pubdate', item), + ) + return feed + +# DEPRECATED class FeedConfiguration: def __init__(self, slug, title_cb, link_cb, description_cb, get_list_func_cb, get_list_kwargs, param_func=None, param_kwargs_cb=None, get_list_kwargs_cb=None, get_pubdate_cb=None, @@ -118,15 +199,18 @@ def _get_feed_generator_object(self, param): # global dict used by register_feed and get_registered_feed _registered_feeds = {} +# DEPRECATED class FeedIsNotRegistered(Exception): pass -class FeedRequiresParam(Exception): - pass - +# DEPRECATED def register_feed(feed): _registered_feeds[feed.slug] = feed +def register_feeds(*feeds): + for f in feeds: + _registered_feeds[f.slug] = f + def get_registered_feed(slug): # try to load a RSS settings module so that feeds can be registered try: @@ -137,4 +221,3 @@ def get_registered_feed(slug): return _registered_feeds[slug] except KeyError: raise FeedIsNotRegistered - diff --git a/django/views/rss/rss.py b/django/views/rss/rss.py index 4f77307a91c9f..97c2f22dc4880 100644 --- a/django/views/rss/rss.py +++ b/django/views/rss/rss.py @@ -5,7 +5,7 @@ def feed(request, slug, param=None): try: f = rss.get_registered_feed(slug).get_feed(param) - except rss.FeedIsNotRegistered: + except (rss.FeedIsNotRegistered, rss.FeedDoesNotExist): raise Http404 response = HttpResponse(mimetype='application/xml') f.write(response, 'utf-8')