diff --git a/django/contrib/syndication/feeds.py b/django/contrib/syndication/feeds.py index 8b49334fec..49b34858dc 100644 --- a/django/contrib/syndication/feeds.py +++ b/django/contrib/syndication/feeds.py @@ -27,8 +27,11 @@ class Feed: except AttributeError: raise ImproperlyConfigured, "Give your %s class a get_absolute_url() method, or define an item_link() method in your Feed class." % item.__class__.__name__ - def __get_dynamic_attr(self, attname, obj): - attr = getattr(self, attname) + def __get_dynamic_attr(self, attname, obj, default=None): + try: + attr = getattr(self, attname) + except AttributeError: + return default if callable(attr): try: return attr(obj) @@ -59,6 +62,9 @@ class Feed: description = self.__get_dynamic_attr('description', obj), language = LANGUAGE_CODE.decode(), feed_url = add_domain(current_site, self.feed_url), + author_name = self.__get_dynamic_attr('author_name', obj), + author_link = self.__get_dynamic_attr('author_link', obj), + author_email = self.__get_dynamic_attr('author_email', obj), ) try: @@ -80,6 +86,12 @@ class Feed: length = str(self.__get_dynamic_attr('item_enclosure_length', item)).decode('utf-8'), mime_type = self.__get_dynamic_attr('item_enclosure_mime_type', item).decode('utf-8'), ) + author_name = self.__get_dynamic_attr('item_author_name', item) + if author_name is not None: + author_email = self.__get_dynamic_attr('item_author_email', item) + author_link = self.__get_dynamic_attr('item_author_link', item) + else: + author_email = author_link = None feed.add_item( title = title_template.render(Context({'obj': item, 'site': current_site})).decode('utf-8'), link = link, @@ -87,5 +99,8 @@ class Feed: unique_id = link, enclosure = enc, pubdate = self.__get_dynamic_attr('item_pubdate', item), + author_name = author_name, + author_email = author_email, + author_link = author_link, ) return feed diff --git a/django/utils/feedgenerator.py b/django/utils/feedgenerator.py index a8dd5c39df..22db5abe7f 100644 --- a/django/utils/feedgenerator.py +++ b/django/utils/feedgenerator.py @@ -58,7 +58,7 @@ class SyndicationFeed: self.items = [] def add_item(self, title, link, description, author_email=None, - author_name=None, pubdate=None, comments=None, + author_name=None, author_link=None, pubdate=None, comments=None, unique_id=None, enclosure=None, categories=()): """ Adds an item to the feed. All args are expected to be Python Unicode @@ -71,6 +71,7 @@ class SyndicationFeed: 'description': description, 'author_email': author_email, 'author_name': author_name, + 'author_link': author_link, 'pubdate': pubdate, 'comments': comments, 'unique_id': unique_id, @@ -226,6 +227,8 @@ class Atom1Feed(SyndicationFeed): handler.addQuickElement(u"name", item['author_name']) if item['author_email'] is not None: handler.addQuickElement(u"email", item['author_email']) + if item['author_link'] is not None: + handler.addQuickElement(u"uri", item['author_link']) handler.endElement(u"author") # Unique ID. diff --git a/docs/syndication_feeds.txt b/docs/syndication_feeds.txt index 453fe71e9d..94c10180ad 100644 --- a/docs/syndication_feeds.txt +++ b/docs/syndication_feeds.txt @@ -386,6 +386,55 @@ This example illustrates all possible attributes and methods for a ``Feed`` clas description = 'Foo bar baz.' # Hard-coded description. + # AUTHOR NAME --One of the following three is optional. The framework + # looks for them in this order. + + def author_name(self, obj): + """ + Takes the object returned by get_object() and returns the feed's + author's name as a normal Python string. + """ + + def author_name(self): + """ + Returns the feed's author's name as a normal Python string. + """ + + author_name = 'Sally Smith' # Hard-coded author name. + + # AUTHOR E-MAIL --One of the following three is optional. The framework + # looks for them in this order. + + def author_email(self, obj): + """ + Takes the object returned by get_object() and returns the feed's + author's e-mail as a normal Python string. + """ + + def author_name(self): + """ + Returns the feed's author's e-mail as a normal Python string. + """ + + author_email = 'test@example.com' # Hard-coded author e-mail. + + # AUTHOR LINK --One of the following three is optional. The framework + # looks for them in this order. In each case, the URL should include + # the "http://" and domain name. + + def author_link(self, obj): + """ + Takes the object returned by get_object() and returns the feed's + author's URL as a normal Python string. + """ + + def author_link(self): + """ + Returns the feed's author's URL as a normal Python string. + """ + + author_link = 'http://www.example.com/' # Hard-coded author URL. + # ITEMS -- One of the following three is required. The framework looks # for them in this order. @@ -428,6 +477,59 @@ This example illustrates all possible attributes and methods for a ``Feed`` clas Returns the URL for every item in the feed. """ + # ITEM AUTHOR NAME --One of the following three is optional. The + # framework looks for them in this order. + + def item_author_name(self, item): + """ + Takes an item, as returned by items(), and returns the item's + author's name as a normal Python string. + """ + + def item_author_name(self): + """ + Returns the author name for every item in the feed. + """ + + item_author_name = 'Sally Smith' # Hard-coded author name. + + # ITEM AUTHOR E-MAIL --One of the following three is optional. The + # framework looks for them in this order. + # + # If you specify this, you must specify item_author_name. + + def item_author_email(self, obj): + """ + Takes an item, as returned by items(), and returns the item's + author's e-mail as a normal Python string. + """ + + def item_author_email(self): + """ + Returns the author e-mail for every item in the feed. + """ + + item_author_email = 'test@example.com' # Hard-coded author e-mail. + + # ITEM AUTHOR LINK --One of the following three is optional. The + # framework looks for them in this order. In each case, the URL should + # include the "http://" and domain name. + # + # If you specify this, you must specify item_author_name. + + def item_author_link(self, obj): + """ + Takes an item, as returned by items(), and returns the item's + author's URL as a normal Python string. + """ + + def item_author_link(self): + """ + Returns the author URL for every item in the feed. + """ + + item_author_link = 'http://www.example.com/' # Hard-coded author URL. + # ITEM ENCLOSURE URL -- One of these three is required if you're # publishing enclosures. The framework looks for them in this order.