web/lib/django/utils/feedgenerator.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
    17 
    17 
    18 For definitions of the different versions of RSS, see:
    18 For definitions of the different versions of RSS, see:
    19 http://diveintomark.org/archives/2004/02/04/incompatible-rss
    19 http://diveintomark.org/archives/2004/02/04/incompatible-rss
    20 """
    20 """
    21 
    21 
    22 import re
       
    23 import datetime
    22 import datetime
       
    23 import urlparse
    24 from django.utils.xmlutils import SimplerXMLGenerator
    24 from django.utils.xmlutils import SimplerXMLGenerator
    25 from django.utils.encoding import force_unicode, iri_to_uri
    25 from django.utils.encoding import force_unicode, iri_to_uri
    26 
    26 
    27 def rfc2822_date(date):
    27 def rfc2822_date(date):
    28     # We do this ourselves to be timezone aware, email.Utils is not tz aware.
    28     # We do this ourselves to be timezone aware, email.Utils is not tz aware.
    44         return time_str + "%+03d:%02d" % (hour, minute)
    44         return time_str + "%+03d:%02d" % (hour, minute)
    45     else:
    45     else:
    46         return date.strftime('%Y-%m-%dT%H:%M:%SZ')
    46         return date.strftime('%Y-%m-%dT%H:%M:%SZ')
    47 
    47 
    48 def get_tag_uri(url, date):
    48 def get_tag_uri(url, date):
    49     "Creates a TagURI. See http://diveintomark.org/archives/2004/05/28/howto-atom-id"
    49     """
    50     tag = re.sub('^http://', '', url)
    50     Creates a TagURI.
       
    51 
       
    52     See http://diveintomark.org/archives/2004/05/28/howto-atom-id
       
    53     """
       
    54     url_split = urlparse.urlparse(url)
       
    55 
       
    56     # Python 2.4 didn't have named attributes on split results or the hostname.
       
    57     hostname = getattr(url_split, 'hostname', url_split[1].split(':')[0])
       
    58     path = url_split[2]
       
    59     fragment = url_split[5]
       
    60 
       
    61     d = ''
    51     if date is not None:
    62     if date is not None:
    52         tag = re.sub('/', ',%s:/' % date.strftime('%Y-%m-%d'), tag, 1)
    63         d = ',%s' % date.strftime('%Y-%m-%d')
    53     tag = re.sub('#', '/', tag)
    64     return u'tag:%s%s:%s/%s' % (hostname, d, path, fragment)
    54     return u'tag:' + tag
       
    55 
    65 
    56 class SyndicationFeed(object):
    66 class SyndicationFeed(object):
    57     "Base class for all syndication feeds. Subclasses should provide write()"
    67     "Base class for all syndication feeds. Subclasses should provide write()"
    58     def __init__(self, title, link, description, language=None, author_email=None,
    68     def __init__(self, title, link, description, language=None, author_email=None,
    59             author_name=None, author_link=None, subtitle=None, categories=None,
    69             author_name=None, author_link=None, subtitle=None, categories=None,
    60             feed_url=None, feed_copyright=None, feed_guid=None, ttl=None, **kwargs):
    70             feed_url=None, feed_copyright=None, feed_guid=None, ttl=None, **kwargs):
    61         to_unicode = lambda s: force_unicode(s, strings_only=True)
    71         to_unicode = lambda s: force_unicode(s, strings_only=True)
    62         if categories:
    72         if categories:
    63             categories = [force_unicode(c) for c in categories]
    73             categories = [force_unicode(c) for c in categories]
       
    74         if ttl is not None:
       
    75             # Force ints to unicode
       
    76             ttl = force_unicode(ttl)
    64         self.feed = {
    77         self.feed = {
    65             'title': to_unicode(title),
    78             'title': to_unicode(title),
    66             'link': iri_to_uri(link),
    79             'link': iri_to_uri(link),
    67             'description': to_unicode(description),
    80             'description': to_unicode(description),
    68             'language': to_unicode(language),
    81             'language': to_unicode(language),
    89         enclosure, which is an instance of the Enclosure class.
   102         enclosure, which is an instance of the Enclosure class.
    90         """
   103         """
    91         to_unicode = lambda s: force_unicode(s, strings_only=True)
   104         to_unicode = lambda s: force_unicode(s, strings_only=True)
    92         if categories:
   105         if categories:
    93             categories = [to_unicode(c) for c in categories]
   106             categories = [to_unicode(c) for c in categories]
       
   107         if ttl is not None:
       
   108             # Force ints to unicode
       
   109             ttl = force_unicode(ttl)
    94         item = {
   110         item = {
    95             'title': to_unicode(title),
   111             'title': to_unicode(title),
    96             'link': iri_to_uri(link),
   112             'link': iri_to_uri(link),
    97             'description': to_unicode(description),
   113             'description': to_unicode(description),
    98             'author_email': to_unicode(author_email),
   114             'author_email': to_unicode(author_email),
   184         self.write_items(handler)
   200         self.write_items(handler)
   185         self.endChannelElement(handler)
   201         self.endChannelElement(handler)
   186         handler.endElement(u"rss")
   202         handler.endElement(u"rss")
   187 
   203 
   188     def rss_attributes(self):
   204     def rss_attributes(self):
   189         return {u"version": self._version}
   205         return {u"version": self._version,
       
   206                 u"xmlns:atom": u"http://www.w3.org/2005/Atom"}
   190 
   207 
   191     def write_items(self, handler):
   208     def write_items(self, handler):
   192         for item in self.items:
   209         for item in self.items:
   193             handler.startElement(u'item', self.item_attributes(item))
   210             handler.startElement(u'item', self.item_attributes(item))
   194             self.add_item_elements(handler, item)
   211             self.add_item_elements(handler, item)
   196 
   213 
   197     def add_root_elements(self, handler):
   214     def add_root_elements(self, handler):
   198         handler.addQuickElement(u"title", self.feed['title'])
   215         handler.addQuickElement(u"title", self.feed['title'])
   199         handler.addQuickElement(u"link", self.feed['link'])
   216         handler.addQuickElement(u"link", self.feed['link'])
   200         handler.addQuickElement(u"description", self.feed['description'])
   217         handler.addQuickElement(u"description", self.feed['description'])
       
   218         handler.addQuickElement(u"atom:link", None, {u"rel": u"self", u"href": self.feed['feed_url']})
   201         if self.feed['language'] is not None:
   219         if self.feed['language'] is not None:
   202             handler.addQuickElement(u"language", self.feed['language'])
   220             handler.addQuickElement(u"language", self.feed['language'])
   203         for cat in self.feed['categories']:
   221         for cat in self.feed['categories']:
   204             handler.addQuickElement(u"category", cat)
   222             handler.addQuickElement(u"category", cat)
   205         if self.feed['feed_copyright'] is not None:
   223         if self.feed['feed_copyright'] is not None:
   233             handler.addQuickElement(u"author", "%s (%s)" % \
   251             handler.addQuickElement(u"author", "%s (%s)" % \
   234                 (item['author_email'], item['author_name']))
   252                 (item['author_email'], item['author_name']))
   235         elif item["author_email"]:
   253         elif item["author_email"]:
   236             handler.addQuickElement(u"author", item["author_email"])
   254             handler.addQuickElement(u"author", item["author_email"])
   237         elif item["author_name"]:
   255         elif item["author_name"]:
   238             handler.addQuickElement(u"dc:creator", item["author_name"], {"xmlns:dc": u"http://purl.org/dc/elements/1.1/"})
   256             handler.addQuickElement(u"dc:creator", item["author_name"], {u"xmlns:dc": u"http://purl.org/dc/elements/1.1/"})
   239 
   257 
   240         if item['pubdate'] is not None:
   258         if item['pubdate'] is not None:
   241             handler.addQuickElement(u"pubDate", rfc2822_date(item['pubdate']).decode('utf-8'))
   259             handler.addQuickElement(u"pubDate", rfc2822_date(item['pubdate']).decode('utf-8'))
   242         if item['comments'] is not None:
   260         if item['comments'] is not None:
   243             handler.addQuickElement(u"comments", item['comments'])
   261             handler.addQuickElement(u"comments", item['comments'])