2
0
Эх сурвалжийг харах

Fixed #9800 -- Allow "isPermaLink" attribute in <guid> element of an RSS item.

Thanks @rtnpro for the patch!
Simon Charette 12 жил өмнө
parent
commit
5449240c54

+ 2 - 0
django/contrib/syndication/views.py

@@ -184,6 +184,8 @@ class Feed(object):
                 link = link,
                 link = link,
                 description = description,
                 description = description,
                 unique_id = self.__get_dynamic_attr('item_guid', item, link),
                 unique_id = self.__get_dynamic_attr('item_guid', item, link),
+                unique_id_is_permalink = self.__get_dynamic_attr(
+                    'item_guid_is_permalink', item),
                 enclosure = enc,
                 enclosure = enc,
                 pubdate = pubdate,
                 pubdate = pubdate,
                 author_name = author_name,
                 author_name = author_name,

+ 8 - 3
django/utils/feedgenerator.py

@@ -113,8 +113,8 @@ class SyndicationFeed(object):
 
 
     def add_item(self, title, link, description, author_email=None,
     def add_item(self, title, link, description, author_email=None,
         author_name=None, author_link=None, pubdate=None, comments=None,
         author_name=None, author_link=None, pubdate=None, comments=None,
-        unique_id=None, enclosure=None, categories=(), item_copyright=None,
+        unique_id=None, unique_id_is_permalink=None, enclosure=None,
-        ttl=None, **kwargs):
+        categories=(), item_copyright=None, ttl=None, **kwargs):
         """
         """
         Adds an item to the feed. All args are expected to be Python Unicode
         Adds an item to the feed. All args are expected to be Python Unicode
         objects except pubdate, which is a datetime.datetime object, and
         objects except pubdate, which is a datetime.datetime object, and
@@ -136,6 +136,7 @@ class SyndicationFeed(object):
             'pubdate': pubdate,
             'pubdate': pubdate,
             'comments': to_unicode(comments),
             'comments': to_unicode(comments),
             'unique_id': to_unicode(unique_id),
             'unique_id': to_unicode(unique_id),
+            'unique_id_is_permalink': unique_id_is_permalink,
             'enclosure': enclosure,
             'enclosure': enclosure,
             'categories': categories or (),
             'categories': categories or (),
             'item_copyright': to_unicode(item_copyright),
             'item_copyright': to_unicode(item_copyright),
@@ -280,7 +281,11 @@ class Rss201rev2Feed(RssFeed):
         if item['comments'] is not None:
         if item['comments'] is not None:
             handler.addQuickElement("comments", item['comments'])
             handler.addQuickElement("comments", item['comments'])
         if item['unique_id'] is not None:
         if item['unique_id'] is not None:
-            handler.addQuickElement("guid", item['unique_id'])
+            guid_attrs = {}
+            if isinstance(item.get('unique_id_is_permalink'), bool):
+                guid_attrs['isPermaLink'] = str(
+                    item['unique_id_is_permalink']).lower()
+            handler.addQuickElement("guid", item['unique_id'], guid_attrs)
         if item['ttl'] is not None:
         if item['ttl'] is not None:
             handler.addQuickElement("ttl", item['ttl'])
             handler.addQuickElement("ttl", item['ttl'])
 
 

+ 12 - 0
docs/ref/contrib/syndication.txt

@@ -624,6 +624,18 @@ This example illustrates all possible attributes and methods for a
             Takes an item, as return by items(), and returns the item's ID.
             Takes an item, as return by items(), and returns the item's ID.
             """
             """
 
 
+        # ITEM_GUID_IS_PERMALINK -- The following method is optional. If
+        # provided, it sets the 'isPermaLink' attribute of an item's
+        # GUID element. This method is used only when 'item_guid' is
+        # specified.
+
+        def item_guid_is_permalink(self, obj):
+            """
+            Takes an item, as returned by items(), and returns a boolean.
+            """
+
+        item_guid_is_permalink = False  # Hard coded value
+
         # ITEM AUTHOR NAME -- One of the following three is optional. The
         # ITEM AUTHOR NAME -- One of the following three is optional. The
         # framework looks for them in this order.
         # framework looks for them in this order.
 
 

+ 13 - 0
tests/regressiontests/syndication/feeds.py

@@ -42,6 +42,19 @@ class TestRss2Feed(views.Feed):
     item_copyright = 'Copyright (c) 2007, Sally Smith'
     item_copyright = 'Copyright (c) 2007, Sally Smith'
 
 
 
 
+class TestRss2FeedWithGuidIsPermaLinkTrue(TestRss2Feed):
+    def item_guid_is_permalink(self, item):
+        return True
+
+
+class TestRss2FeedWithGuidIsPermaLinkFalse(TestRss2Feed):
+    def item_guid(self, item):
+        return str(item.pk)
+
+    def item_guid_is_permalink(self, item):
+        return False
+
+
 class TestRss091Feed(TestRss2Feed):
 class TestRss091Feed(TestRss2Feed):
     feed_type = feedgenerator.RssUserland091Feed
     feed_type = feedgenerator.RssUserland091Feed
 
 

+ 35 - 1
tests/regressiontests/syndication/tests.py

@@ -103,9 +103,43 @@ class SyndicationFeedTest(FeedTestCase):
             'author': 'test@example.com (Sally Smith)',
             'author': 'test@example.com (Sally Smith)',
         })
         })
         self.assertCategories(items[0], ['python', 'testing'])
         self.assertCategories(items[0], ['python', 'testing'])
-
         for item in items:
         for item in items:
             self.assertChildNodes(item, ['title', 'link', 'description', 'guid', 'category', 'pubDate', 'author'])
             self.assertChildNodes(item, ['title', 'link', 'description', 'guid', 'category', 'pubDate', 'author'])
+            # Assert that <guid> does not have any 'isPermaLink' attribute
+            self.assertIsNone(item.getElementsByTagName(
+                'guid')[0].attributes.get('isPermaLink'))
+
+    def test_rss2_feed_guid_permalink_false(self):
+        """
+        Test if the 'isPermaLink' attribute of <guid> element of an item
+        in the RSS feed is 'false'.
+        """
+        response = self.client.get(
+            '/syndication/rss2/guid_ispermalink_false/')
+        doc = minidom.parseString(response.content)
+        chan = doc.getElementsByTagName(
+            'rss')[0].getElementsByTagName('channel')[0]
+        items = chan.getElementsByTagName('item')
+        for item in items:
+            self.assertEqual(
+                item.getElementsByTagName('guid')[0].attributes.get(
+                    'isPermaLink').value, "false")
+
+    def test_rss2_feed_guid_permalink_true(self):
+        """
+        Test if the 'isPermaLink' attribute of <guid> element of an item
+        in the RSS feed is 'true'.
+        """
+        response = self.client.get(
+            '/syndication/rss2/guid_ispermalink_true/')
+        doc = minidom.parseString(response.content)
+        chan = doc.getElementsByTagName(
+            'rss')[0].getElementsByTagName('channel')[0]
+        items = chan.getElementsByTagName('item')
+        for item in items:
+            self.assertEqual(
+                item.getElementsByTagName('guid')[0].attributes.get(
+                    'isPermaLink').value, "true")
 
 
     def test_rss091_feed(self):
     def test_rss091_feed(self):
         """
         """

+ 4 - 0
tests/regressiontests/syndication/urls.py

@@ -8,6 +8,10 @@ from . import feeds
 urlpatterns = patterns('django.contrib.syndication.views',
 urlpatterns = patterns('django.contrib.syndication.views',
     (r'^syndication/complex/(?P<foo>.*)/$', feeds.ComplexFeed()),
     (r'^syndication/complex/(?P<foo>.*)/$', feeds.ComplexFeed()),
     (r'^syndication/rss2/$', feeds.TestRss2Feed()),
     (r'^syndication/rss2/$', feeds.TestRss2Feed()),
+    (r'^syndication/rss2/guid_ispermalink_true/$',
+        feeds.TestRss2FeedWithGuidIsPermaLinkTrue()),
+    (r'^syndication/rss2/guid_ispermalink_false/$',
+        feeds.TestRss2FeedWithGuidIsPermaLinkFalse()),
     (r'^syndication/rss091/$', feeds.TestRss091Feed()),
     (r'^syndication/rss091/$', feeds.TestRss091Feed()),
     (r'^syndication/no_pubdate/$', feeds.TestNoPubdateFeed()),
     (r'^syndication/no_pubdate/$', feeds.TestNoPubdateFeed()),
     (r'^syndication/atom/$', feeds.TestAtomFeed()),
     (r'^syndication/atom/$', feeds.TestAtomFeed()),