diff --git a/django/contrib/syndication/feeds.py b/django/contrib/syndication/feeds.py index b1d0cf02c7..547afb17f3 100644 --- a/django/contrib/syndication/feeds.py +++ b/django/contrib/syndication/feeds.py @@ -83,6 +83,7 @@ class Feed(object): author_email = self.__get_dynamic_attr('author_email', obj), categories = self.__get_dynamic_attr('categories', obj), feed_copyright = self.__get_dynamic_attr('feed_copyright', obj), + feed_guid = self.__get_dynamic_attr('feed_guid', obj), ) try: @@ -114,7 +115,7 @@ class Feed(object): title = title_tmp.render(Context({'obj': item, 'site': current_site})), link = link, description = description_tmp.render(Context({'obj': item, 'site': current_site})), - unique_id = link, + unique_id = self.__get_dynamic_attr('item_guid', item, link), enclosure = enc, pubdate = self.__get_dynamic_attr('item_pubdate', item), author_name = author_name, diff --git a/django/utils/feedgenerator.py b/django/utils/feedgenerator.py index 064ec19120..6b6dedfbe9 100644 --- a/django/utils/feedgenerator.py +++ b/django/utils/feedgenerator.py @@ -41,7 +41,7 @@ class SyndicationFeed(object): "Base class for all syndication feeds. Subclasses should provide write()" def __init__(self, title, link, description, language=None, author_email=None, author_name=None, author_link=None, subtitle=None, categories=None, - feed_url=None, feed_copyright=None): + feed_url=None, feed_copyright=None, feed_guid=None): to_unicode = lambda s: force_unicode(s, strings_only=True) if categories: categories = [force_unicode(c) for c in categories] @@ -57,6 +57,7 @@ class SyndicationFeed(object): 'categories': categories or (), 'feed_url': iri_to_uri(feed_url), 'feed_copyright': to_unicode(feed_copyright), + 'id': feed_guid or link, } self.items = [] @@ -213,7 +214,7 @@ class Atom1Feed(SyndicationFeed): handler.addQuickElement(u"link", "", {u"rel": u"alternate", u"href": self.feed['link']}) if self.feed['feed_url'] is not None: handler.addQuickElement(u"link", "", {u"rel": u"self", u"href": self.feed['feed_url']}) - handler.addQuickElement(u"id", self.feed['link']) + handler.addQuickElement(u"id", self.feed['id']) handler.addQuickElement(u"updated", rfc3339_date(self.latest_post_date()).decode('ascii')) if self.feed['author_name'] is not None: handler.startElement(u"author", {}) diff --git a/docs/syndication_feeds.txt b/docs/syndication_feeds.txt index 2a03e6d5a6..2af287cf84 100644 --- a/docs/syndication_feeds.txt +++ b/docs/syndication_feeds.txt @@ -416,6 +416,24 @@ This example illustrates all possible attributes and methods for a ``Feed`` clas link = '/foo/bar/' # Hard-coded link. + # GUID -- One of the following three is optional. The framework looks + # for them in this order. This property is only used for Atom feeds + # (where it is the feed-level id element). If not provided, the feed + # link is used as the id. + + def feed_guid(self, obj): + """ + Takes the object returned by get_object() and returns the globally + unique id for the feed as a normal Python string. + """ + + def feed_guid(self): + """ + Returns the feed's globally unique id as a normal Python string. + """ + + feed_guid = '/foo/bar/1234' # Hard-coded guid. + # DESCRIPTION -- One of the following three is required. The framework # looks for them in this order. @@ -556,6 +574,15 @@ This example illustrates all possible attributes and methods for a ``Feed`` clas Returns the URL for every item in the feed. """ + # ITEM_GUID -- The following method is optional. This property is + # only used for Atom feeds (it is the id element for an item in an + # Atom feed). If not provided, the item's link is used by default. + + def item_guid(self, obj): + """ + Takes an item, as return by items(), and returns the item's id. + """ + # ITEM AUTHOR NAME --One of the following three is optional. The # framework looks for them in this order.