We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[v23] Renommer un contenu l'envoit deux fois dans les flux rss
En jetant un œil aux [flux rss des billets](https://beta.zestedesavoir.com/tribunes/flux/rss/), on se rend compte que le billet `Un gros Troll de plus sur Javascript` est présent 2 fois.

C'est du au fait que j'ai publié la première fois le billet avec un autre nom. A la deuxième publication, le nom a été modifié et ça apparait deux fois inutilement dans les flux rss.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `zds/tutorialv2/managers.py`
Content:
```
1 # -*- coding: utf-8 -*-
2 
3 from django.conf import settings
4 from django.db import models
5 from django.db.models import Count, F
6 
7 from zds.utils.models import Tag
8 from django.utils.translation import ugettext_lazy as _
9 
10 
11 class PublishedContentManager(models.Manager):
12     """
13     Custom published content manager.
14     """
15 
16     def last_contents_of_a_member_loaded(self, author, _type=None):
17         """
18         Get contents published by author depends on settings.ZDS_APP['content']['user_page_number']
19 
20         :param author:
21         :param _type: subtype to filter request
22         :return:
23         :rtype: django.db.models.QuerySet
24         """
25 
26         queryset = self.prefetch_related('content') \
27             .prefetch_related('content__authors') \
28             .prefetch_related('content__subcategory') \
29             .filter(content__authors__in=[author]) \
30             .filter(must_redirect=False)
31 
32         if _type:
33             queryset = queryset.filter(content_type=_type)
34 
35         public_contents = queryset.order_by('-publication_date').all()[:settings.ZDS_APP['content']['user_page_number']]
36         return public_contents
37 
38     def last_tutorials_of_a_member_loaded(self, author):
39         return self.last_contents_of_a_member_loaded(author, _type='TUTORIAL')
40 
41     def last_articles_of_a_member_loaded(self, author):
42         return self.last_contents_of_a_member_loaded(author, _type='ARTICLE')
43 
44     def last_opinions_of_a_member_loaded(self, author):
45         return self.last_contents_of_a_member_loaded(author, _type='OPINION')
46 
47     def get_contents_count(self):
48         """
49         :rtype: int
50         """
51         return self.filter(must_redirect=False) \
52                    .count()
53 
54     def get_top_tags(self, displayed_types, limit=-1):
55         """
56         Retrieve all most rated tags.
57 
58         :param displayed_types:
59         :param limit: if ``-1`` or ``0`` => no limit. Else just takes the provided number of elements.
60         :return:
61         """
62         published = self.filter(
63             must_redirect=False,
64             content__type__in=displayed_types).values('content__tags').distinct()
65         tags_pk = [tag['content__tags'] for tag in published]
66         queryset = Tag.objects\
67             .filter(pk__in=tags_pk, publishablecontent__public_version__isnull=False,
68                     publishablecontent__type__in=displayed_types) \
69             .annotate(num_content=Count('publishablecontent')) \
70             .order_by('-num_content', 'title')
71         if limit > 0:
72             queryset = queryset[:limit]
73         return queryset
74 
75     def transfer_paternity(self, unsubscribed_user, replacement_author):
76         """
77         erase or transfer the paternity of all published content owned by a user.
78         if a content has more than one author, the unregistering author just leave its redaction\
79         else just mark ``replacement_author`` as the new author
80 
81         """
82         for published in self.filter(authors__in=[unsubscribed_user]):
83             if published.authors.count() == 1:
84                 published.authors.add(replacement_author)
85             published.authors.remove(unsubscribed_user)
86             published.save()
87 
88 
89 class PublishableContentManager(models.Manager):
90     """..."""
91 
92     def transfer_paternity(self, unregistered_user, replacement_author, gallery_class):
93         """
94         Erases or transfers the paternity of all publishable content owned by a user. \
95         If a content has more than one author, the unregistering author simply leaves its author list, \
96         otherwise their published content are sent to ``replacement_author``, \
97         unpublished content are deleted and their beta topics closed.
98 
99         :param unregistered_user: the user to be unregistered
100         :param replacement_author: the new author
101         :param gallery_class: the class to link tutorial with gallery (perhaps overkill :p)
102         """
103         for content in self.filter(authors__in=[unregistered_user]):
104             # we delete content only if not published with only one author
105             if not content.in_public() and content.authors.count() == 1:
106                 if content.in_beta() and content.beta_topic:
107                     beta_topic = content.beta_topic
108                     beta_topic.is_locked = True
109                     beta_topic.save()
110                     first_post = beta_topic.first_post()
111                     first_post.update_content(_(u"# Le tutoriel présenté par ce topic n'existe plus."))
112                     first_post.save()
113                 content.delete()
114             else:
115                 if content.authors.count() == 1:
116                     content.authors.add(replacement_author)
117                     external_gallery = gallery_class()
118                     external_gallery.user = replacement_author
119                     external_gallery.gallery = content.gallery
120                     external_gallery.mode = 'W'
121                     external_gallery.save()
122                     gallery_class.objects.filter(user=unregistered_user).filter(gallery=content.gallery).delete()
123 
124                     content.authors.remove(unregistered_user)
125                     # we add a sentence to the content's introduction stating it was written by a former member.
126                     versioned = content.load_version()
127                     title = versioned.title
128                     introduction = _(u'[[i]]\n|Ce contenu a été rédigé par {} qui a quitté le site.\n\n')\
129                         .format(unregistered_user.username) + versioned.get_introduction()
130                     conclusion = versioned.get_conclusion()
131                     sha = versioned.repo_update(title, introduction, conclusion,
132                                                 commit_message='Author unsubscribed',
133                                                 do_commit=True, update_slug=True)
134                     content.sha_draft = sha
135                     content.save()
136 
137     def get_last_tutorials(self):
138         """
139         This depends on settings.ZDS_APP['tutorial']['home_number'] parameter
140 
141         :return: lit of last published content
142         :rtype: list
143         """
144         home_number = settings.ZDS_APP['tutorial']['home_number']
145         all_contents = self.filter(type='TUTORIAL') \
146                            .filter(public_version__isnull=False) \
147                            .prefetch_related('authors') \
148                            .prefetch_related('authors__profile') \
149                            .select_related('last_note') \
150                            .select_related('public_version') \
151                            .prefetch_related('subcategory') \
152                            .prefetch_related('tags') \
153                            .order_by('-public_version__publication_date')[:home_number]
154         published = []
155         for content in all_contents:
156             content.public_version.content = content
157             published.append(content.public_version)
158         return published
159 
160     def get_last_articles(self):
161         """
162         ..attention:
163             this one uses a raw subquery for historical reasons. It will hopefully be replaced one day by an
164             ORM primitive.
165 
166         :return: list of last articles expanded with 'count_note' property that prefetches number of comments
167         :rtype: list
168         """
169         sub_query = 'SELECT COUNT(*) FROM {} WHERE {}={}'.format(
170             'tutorialv2_contentreaction',
171             'tutorialv2_contentreaction.related_content_id',
172             'tutorialv2_publishedcontent.content_pk',
173         )
174         home_number = settings.ZDS_APP['article']['home_number']
175         all_contents = self.filter(type='ARTICLE') \
176                            .filter(public_version__isnull=False) \
177                            .prefetch_related('authors') \
178                            .prefetch_related('authors__profile') \
179                            .select_related('last_note') \
180                            .select_related('public_version') \
181                            .prefetch_related('subcategory') \
182                            .prefetch_related('tags') \
183                            .extra(select={'count_note': sub_query}) \
184                            .order_by('-public_version__publication_date')[:home_number]
185         published = []
186         for content in all_contents:
187             content.public_version.content = content
188             published.append(content.public_version)
189         return published
190 
191     def get_last_opinions(self):
192         """
193         This depends on settings.ZDS_APP['opinions']['home_number'] parameter.
194 
195         :return: list of last opinions
196         :rtype: list
197         """
198         home_number = settings.ZDS_APP['opinions']['home_number']
199         all_contents = self.filter(type='OPINION') \
200                            .filter(public_version__isnull=False, sha_picked=F('sha_public')) \
201                            .prefetch_related('authors') \
202                            .prefetch_related('authors__profile') \
203                            .select_related('last_note') \
204                            .select_related('public_version') \
205                            .prefetch_related('subcategory') \
206                            .prefetch_related('tags') \
207                            .order_by('-picked_date')[:home_number]
208         published = []
209         for content in all_contents:
210             content.public_version.content = content
211             published.append(content.public_version)
212         return published
213
```

Path: `zds/tutorialv2/feeds.py`
Content:
```
1 # coding: utf-8
2 
3 from django.contrib.syndication.views import Feed
4 from django.conf import settings
5 
6 from django.utils.feedgenerator import Atom1Feed
7 
8 from zds.tutorialv2.models.models_database import PublishedContent
9 from zds.settings import ZDS_APP
10 
11 
12 class LastContentFeedRSS(Feed):
13     """
14     RSS feed for any type of content.
15     """
16     title = u'Contenus sur {}'.format(settings.ZDS_APP['site']['litteral_name'])
17     description = u'Les derniers contenus parus sur {}.'.format(settings.ZDS_APP['site']['litteral_name'])
18     link = ''
19     content_type = None
20 
21     def items(self):
22         """
23         :return: The last (typically 5) contents (sorted by publication date).
24         If `self.type` is not `None`, the contents will only be of this type.
25         """
26         contents = PublishedContent.objects\
27             .prefetch_related('content')\
28             .prefetch_related('content__authors')
29 
30         if self.content_type is not None:
31             contents = contents.filter(content_type=self.content_type)
32 
33         return contents.order_by('-publication_date')[:ZDS_APP['content']['feed_length']]
34 
35     def item_title(self, item):
36         return item.content.title
37 
38     def item_pubdate(self, item):
39         return item.publication_date
40 
41     def item_description(self, item):
42         return item.content.description
43 
44     def item_author_name(self, item):
45         authors_list = item.content.authors.all()
46         authors = []
47         for authors_obj in authors_list:
48             authors.append(authors_obj.username)
49         authors = ', '.join(authors)
50         return authors
51 
52     def item_link(self, item):
53         return item.get_absolute_url_online()
54 
55 
56 class LastContentFeedATOM(LastContentFeedRSS):
57     feed_type = Atom1Feed
58     subtitle = LastContentFeedRSS.description
59 
60 
61 class LastTutorialsFeedRSS(LastContentFeedRSS):
62     """
63     Redefinition of `LastContentFeedRSS` for tutorials only
64     """
65     content_type = 'TUTORIAL'
66     link = '/tutoriels/'
67     title = u'Tutoriels sur {}'.format(settings.ZDS_APP['site']['litteral_name'])
68     description = u'Les derniers tutoriels parus sur {}.'.format(settings.ZDS_APP['site']['litteral_name'])
69 
70 
71 class LastTutorialsFeedATOM(LastTutorialsFeedRSS):
72     feed_type = Atom1Feed
73     subtitle = LastTutorialsFeedRSS.description
74 
75 
76 class LastArticlesFeedRSS(LastContentFeedRSS):
77     """
78     Redefinition of `LastContentFeedRSS` for articles only
79     """
80     content_type = 'ARTICLE'
81     link = '/articles/'
82     title = u'Articles sur {}'.format(settings.ZDS_APP['site']['litteral_name'])
83     description = u'Les derniers articles parus sur {}.'.format(settings.ZDS_APP['site']['litteral_name'])
84 
85 
86 class LastArticlesFeedATOM(LastArticlesFeedRSS):
87     feed_type = Atom1Feed
88     subtitle = LastArticlesFeedRSS.description
89 
90 
91 class LastOpinionsFeedRSS(LastContentFeedRSS):
92     """
93     Redefinition of `LastContentFeedRSS` for opinions only
94     """
95     content_type = 'OPINION'
96     link = '/tribunes/'
97     title = u'Tribunes sur {}'.format(settings.ZDS_APP['site']['litteral_name'])
98     description = u'Les derniers billets des tribunes parus sur {}.'.format(
99         settings.ZDS_APP['site']['litteral_name'])
100 
101 
102 class LastOpinionsFeedATOM(LastOpinionsFeedRSS):
103     feed_type = Atom1Feed
104     subtitle = LastOpinionsFeedRSS.description
105
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/zds/tutorialv2/feeds.py b/zds/tutorialv2/feeds.py
--- a/zds/tutorialv2/feeds.py
+++ b/zds/tutorialv2/feeds.py
@@ -23,14 +23,9 @@
         :return: The last (typically 5) contents (sorted by publication date).
         If `self.type` is not `None`, the contents will only be of this type.
         """
-        contents = PublishedContent.objects\
-            .prefetch_related('content')\
-            .prefetch_related('content__authors')
+        contents = PublishedContent.objects.published_contents(self.content_type)[:ZDS_APP['content']['feed_length']]
 
-        if self.content_type is not None:
-            contents = contents.filter(content_type=self.content_type)
-
-        return contents.order_by('-publication_date')[:ZDS_APP['content']['feed_length']]
+        return contents
 
     def item_title(self, item):
         return item.content.title
diff --git a/zds/tutorialv2/managers.py b/zds/tutorialv2/managers.py
--- a/zds/tutorialv2/managers.py
+++ b/zds/tutorialv2/managers.py
@@ -13,26 +13,37 @@
     Custom published content manager.
     """
 
-    def last_contents_of_a_member_loaded(self, author, _type=None):
+    def published_contents(self, _type=None):
         """
-        Get contents published by author depends on settings.ZDS_APP['content']['user_page_number']
+        Get contents published order by date.
 
-        :param author:
-        :param _type: subtype to filter request
         :return:
         :rtype: django.db.models.QuerySet
         """
-
         queryset = self.prefetch_related('content') \
             .prefetch_related('content__authors') \
             .prefetch_related('content__subcategory') \
-            .filter(content__authors__in=[author]) \
-            .filter(must_redirect=False)
+            .filter(must_redirect=False) \
+            .order_by('-publication_date')
 
         if _type:
             queryset = queryset.filter(content_type=_type)
 
-        public_contents = queryset.order_by('-publication_date').all()[:settings.ZDS_APP['content']['user_page_number']]
+        return queryset
+
+    def last_contents_of_a_member_loaded(self, author, _type=None):
+        """
+        Get contents published by author depends on settings.ZDS_APP['content']['user_page_number']
+
+        :param author:
+        :param _type: subtype to filter request
+        :return:
+        :rtype: django.db.models.QuerySet
+        """
+        queryset = self.published_contents(_type) \
+            .filter(content__authors__in=[author])
+
+        public_contents = queryset.all()[:settings.ZDS_APP['content']['user_page_number']]
         return public_contents
 
     def last_tutorials_of_a_member_loaded(self, author):

{"golden_diff": "diff --git a/zds/tutorialv2/feeds.py b/zds/tutorialv2/feeds.py\n--- a/zds/tutorialv2/feeds.py\n+++ b/zds/tutorialv2/feeds.py\n@@ -23,14 +23,9 @@\n         :return: The last (typically 5) contents (sorted by publication date).\n         If `self.type` is not `None`, the contents will only be of this type.\n         \"\"\"\n-        contents = PublishedContent.objects\\\n-            .prefetch_related('content')\\\n-            .prefetch_related('content__authors')\n+        contents = PublishedContent.objects.published_contents(self.content_type)[:ZDS_APP['content']['feed_length']]\n \n-        if self.content_type is not None:\n-            contents = contents.filter(content_type=self.content_type)\n-\n-        return contents.order_by('-publication_date')[:ZDS_APP['content']['feed_length']]\n+        return contents\n \n     def item_title(self, item):\n         return item.content.title\ndiff --git a/zds/tutorialv2/managers.py b/zds/tutorialv2/managers.py\n--- a/zds/tutorialv2/managers.py\n+++ b/zds/tutorialv2/managers.py\n@@ -13,26 +13,37 @@\n     Custom published content manager.\n     \"\"\"\n \n-    def last_contents_of_a_member_loaded(self, author, _type=None):\n+    def published_contents(self, _type=None):\n         \"\"\"\n-        Get contents published by author depends on settings.ZDS_APP['content']['user_page_number']\n+        Get contents published order by date.\n \n-        :param author:\n-        :param _type: subtype to filter request\n         :return:\n         :rtype: django.db.models.QuerySet\n         \"\"\"\n-\n         queryset = self.prefetch_related('content') \\\n             .prefetch_related('content__authors') \\\n             .prefetch_related('content__subcategory') \\\n-            .filter(content__authors__in=[author]) \\\n-            .filter(must_redirect=False)\n+            .filter(must_redirect=False) \\\n+            .order_by('-publication_date')\n \n         if _type:\n             queryset = queryset.filter(content_type=_type)\n \n-        public_contents = queryset.order_by('-publication_date').all()[:settings.ZDS_APP['content']['user_page_number']]\n+        return queryset\n+\n+    def last_contents_of_a_member_loaded(self, author, _type=None):\n+        \"\"\"\n+        Get contents published by author depends on settings.ZDS_APP['content']['user_page_number']\n+\n+        :param author:\n+        :param _type: subtype to filter request\n+        :return:\n+        :rtype: django.db.models.QuerySet\n+        \"\"\"\n+        queryset = self.published_contents(_type) \\\n+            .filter(content__authors__in=[author])\n+\n+        public_contents = queryset.all()[:settings.ZDS_APP['content']['user_page_number']]\n         return public_contents\n \n     def last_tutorials_of_a_member_loaded(self, author):\n", "issue": "[v23] Renommer un contenu l'envoit deux fois dans les flux rss\nEn jetant un \u0153il aux [flux rss des billets](https://beta.zestedesavoir.com/tribunes/flux/rss/), on se rend compte que le billet `Un gros Troll de plus sur Javascript` est pr\u00e9sent 2 fois.\r\n\r\nC'est du au fait que j'ai publi\u00e9 la premi\u00e8re fois le billet avec un autre nom. A la deuxi\u00e8me publication, le nom a \u00e9t\u00e9 modifi\u00e9 et \u00e7a apparait deux fois inutilement dans les flux rss.\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n\nfrom django.conf import settings\nfrom django.db import models\nfrom django.db.models import Count, F\n\nfrom zds.utils.models import Tag\nfrom django.utils.translation import ugettext_lazy as _\n\n\nclass PublishedContentManager(models.Manager):\n    \"\"\"\n    Custom published content manager.\n    \"\"\"\n\n    def last_contents_of_a_member_loaded(self, author, _type=None):\n        \"\"\"\n        Get contents published by author depends on settings.ZDS_APP['content']['user_page_number']\n\n        :param author:\n        :param _type: subtype to filter request\n        :return:\n        :rtype: django.db.models.QuerySet\n        \"\"\"\n\n        queryset = self.prefetch_related('content') \\\n            .prefetch_related('content__authors') \\\n            .prefetch_related('content__subcategory') \\\n            .filter(content__authors__in=[author]) \\\n            .filter(must_redirect=False)\n\n        if _type:\n            queryset = queryset.filter(content_type=_type)\n\n        public_contents = queryset.order_by('-publication_date').all()[:settings.ZDS_APP['content']['user_page_number']]\n        return public_contents\n\n    def last_tutorials_of_a_member_loaded(self, author):\n        return self.last_contents_of_a_member_loaded(author, _type='TUTORIAL')\n\n    def last_articles_of_a_member_loaded(self, author):\n        return self.last_contents_of_a_member_loaded(author, _type='ARTICLE')\n\n    def last_opinions_of_a_member_loaded(self, author):\n        return self.last_contents_of_a_member_loaded(author, _type='OPINION')\n\n    def get_contents_count(self):\n        \"\"\"\n        :rtype: int\n        \"\"\"\n        return self.filter(must_redirect=False) \\\n                   .count()\n\n    def get_top_tags(self, displayed_types, limit=-1):\n        \"\"\"\n        Retrieve all most rated tags.\n\n        :param displayed_types:\n        :param limit: if ``-1``\u00a0or ``0`` => no limit. Else just takes the provided number of elements.\n        :return:\n        \"\"\"\n        published = self.filter(\n            must_redirect=False,\n            content__type__in=displayed_types).values('content__tags').distinct()\n        tags_pk = [tag['content__tags'] for tag in published]\n        queryset = Tag.objects\\\n            .filter(pk__in=tags_pk, publishablecontent__public_version__isnull=False,\n                    publishablecontent__type__in=displayed_types) \\\n            .annotate(num_content=Count('publishablecontent')) \\\n            .order_by('-num_content', 'title')\n        if limit > 0:\n            queryset = queryset[:limit]\n        return queryset\n\n    def transfer_paternity(self, unsubscribed_user, replacement_author):\n        \"\"\"\n        erase or transfer the paternity of all published content owned by a user.\n        if a content has more than one author, the unregistering author just leave its redaction\\\n        else just mark ``replacement_author`` as the new author\n\n        \"\"\"\n        for published in self.filter(authors__in=[unsubscribed_user]):\n            if published.authors.count() == 1:\n                published.authors.add(replacement_author)\n            published.authors.remove(unsubscribed_user)\n            published.save()\n\n\nclass PublishableContentManager(models.Manager):\n    \"\"\"...\"\"\"\n\n    def transfer_paternity(self, unregistered_user, replacement_author, gallery_class):\n        \"\"\"\n        Erases or transfers the paternity of all publishable content owned by a user. \\\n        If a content has more than one author, the unregistering author simply leaves its author list, \\\n        otherwise their published content are sent to ``replacement_author``, \\\n        unpublished content are deleted and their beta topics closed.\n\n        :param unregistered_user: the user to be unregistered\n        :param replacement_author: the new author\n        :param gallery_class: the class to link tutorial with gallery (perhaps overkill :p)\n        \"\"\"\n        for content in self.filter(authors__in=[unregistered_user]):\n            # we delete content only if not published with only one author\n            if not content.in_public() and content.authors.count() == 1:\n                if content.in_beta() and content.beta_topic:\n                    beta_topic = content.beta_topic\n                    beta_topic.is_locked = True\n                    beta_topic.save()\n                    first_post = beta_topic.first_post()\n                    first_post.update_content(_(u\"# Le tutoriel pr\u00e9sent\u00e9 par ce topic n'existe plus.\"))\n                    first_post.save()\n                content.delete()\n            else:\n                if content.authors.count() == 1:\n                    content.authors.add(replacement_author)\n                    external_gallery = gallery_class()\n                    external_gallery.user = replacement_author\n                    external_gallery.gallery = content.gallery\n                    external_gallery.mode = 'W'\n                    external_gallery.save()\n                    gallery_class.objects.filter(user=unregistered_user).filter(gallery=content.gallery).delete()\n\n                    content.authors.remove(unregistered_user)\n                    # we add a sentence to the content's introduction stating it was written by a former member.\n                    versioned = content.load_version()\n                    title = versioned.title\n                    introduction = _(u'[[i]]\\n|Ce contenu a \u00e9t\u00e9 r\u00e9dig\u00e9 par {} qui a quitt\u00e9 le site.\\n\\n')\\\n                        .format(unregistered_user.username) + versioned.get_introduction()\n                    conclusion = versioned.get_conclusion()\n                    sha = versioned.repo_update(title, introduction, conclusion,\n                                                commit_message='Author unsubscribed',\n                                                do_commit=True, update_slug=True)\n                    content.sha_draft = sha\n                    content.save()\n\n    def get_last_tutorials(self):\n        \"\"\"\n        This depends on settings.ZDS_APP['tutorial']['home_number'] parameter\n\n        :return: lit of last published content\n        :rtype: list\n        \"\"\"\n        home_number = settings.ZDS_APP['tutorial']['home_number']\n        all_contents = self.filter(type='TUTORIAL') \\\n                           .filter(public_version__isnull=False) \\\n                           .prefetch_related('authors') \\\n                           .prefetch_related('authors__profile') \\\n                           .select_related('last_note') \\\n                           .select_related('public_version') \\\n                           .prefetch_related('subcategory') \\\n                           .prefetch_related('tags') \\\n                           .order_by('-public_version__publication_date')[:home_number]\n        published = []\n        for content in all_contents:\n            content.public_version.content = content\n            published.append(content.public_version)\n        return published\n\n    def get_last_articles(self):\n        \"\"\"\n        ..attention:\n            this one uses a raw subquery for historical reasons. It will hopefully be replaced one day by an\n            ORM primitive.\n\n        :return: list of last articles expanded with 'count_note' property that prefetches number of comments\n        :rtype: list\n        \"\"\"\n        sub_query = 'SELECT COUNT(*) FROM {} WHERE {}={}'.format(\n            'tutorialv2_contentreaction',\n            'tutorialv2_contentreaction.related_content_id',\n            'tutorialv2_publishedcontent.content_pk',\n        )\n        home_number = settings.ZDS_APP['article']['home_number']\n        all_contents = self.filter(type='ARTICLE') \\\n                           .filter(public_version__isnull=False) \\\n                           .prefetch_related('authors') \\\n                           .prefetch_related('authors__profile') \\\n                           .select_related('last_note') \\\n                           .select_related('public_version') \\\n                           .prefetch_related('subcategory') \\\n                           .prefetch_related('tags') \\\n                           .extra(select={'count_note': sub_query}) \\\n                           .order_by('-public_version__publication_date')[:home_number]\n        published = []\n        for content in all_contents:\n            content.public_version.content = content\n            published.append(content.public_version)\n        return published\n\n    def get_last_opinions(self):\n        \"\"\"\n        This depends on settings.ZDS_APP['opinions']['home_number'] parameter.\n\n        :return: list of last opinions\n        :rtype: list\n        \"\"\"\n        home_number = settings.ZDS_APP['opinions']['home_number']\n        all_contents = self.filter(type='OPINION') \\\n                           .filter(public_version__isnull=False, sha_picked=F('sha_public')) \\\n                           .prefetch_related('authors') \\\n                           .prefetch_related('authors__profile') \\\n                           .select_related('last_note') \\\n                           .select_related('public_version') \\\n                           .prefetch_related('subcategory') \\\n                           .prefetch_related('tags') \\\n                           .order_by('-picked_date')[:home_number]\n        published = []\n        for content in all_contents:\n            content.public_version.content = content\n            published.append(content.public_version)\n        return published\n", "path": "zds/tutorialv2/managers.py"}, {"content": "# coding: utf-8\n\nfrom django.contrib.syndication.views import Feed\nfrom django.conf import settings\n\nfrom django.utils.feedgenerator import Atom1Feed\n\nfrom zds.tutorialv2.models.models_database import PublishedContent\nfrom zds.settings import ZDS_APP\n\n\nclass LastContentFeedRSS(Feed):\n    \"\"\"\n    RSS feed for any type of content.\n    \"\"\"\n    title = u'Contenus sur {}'.format(settings.ZDS_APP['site']['litteral_name'])\n    description = u'Les derniers contenus parus sur {}.'.format(settings.ZDS_APP['site']['litteral_name'])\n    link = ''\n    content_type = None\n\n    def items(self):\n        \"\"\"\n        :return: The last (typically 5) contents (sorted by publication date).\n        If `self.type` is not `None`, the contents will only be of this type.\n        \"\"\"\n        contents = PublishedContent.objects\\\n            .prefetch_related('content')\\\n            .prefetch_related('content__authors')\n\n        if self.content_type is not None:\n            contents = contents.filter(content_type=self.content_type)\n\n        return contents.order_by('-publication_date')[:ZDS_APP['content']['feed_length']]\n\n    def item_title(self, item):\n        return item.content.title\n\n    def item_pubdate(self, item):\n        return item.publication_date\n\n    def item_description(self, item):\n        return item.content.description\n\n    def item_author_name(self, item):\n        authors_list = item.content.authors.all()\n        authors = []\n        for authors_obj in authors_list:\n            authors.append(authors_obj.username)\n        authors = ', '.join(authors)\n        return authors\n\n    def item_link(self, item):\n        return item.get_absolute_url_online()\n\n\nclass LastContentFeedATOM(LastContentFeedRSS):\n    feed_type = Atom1Feed\n    subtitle = LastContentFeedRSS.description\n\n\nclass LastTutorialsFeedRSS(LastContentFeedRSS):\n    \"\"\"\n    Redefinition of `LastContentFeedRSS` for tutorials only\n    \"\"\"\n    content_type = 'TUTORIAL'\n    link = '/tutoriels/'\n    title = u'Tutoriels sur {}'.format(settings.ZDS_APP['site']['litteral_name'])\n    description = u'Les derniers tutoriels parus sur {}.'.format(settings.ZDS_APP['site']['litteral_name'])\n\n\nclass LastTutorialsFeedATOM(LastTutorialsFeedRSS):\n    feed_type = Atom1Feed\n    subtitle = LastTutorialsFeedRSS.description\n\n\nclass LastArticlesFeedRSS(LastContentFeedRSS):\n    \"\"\"\n    Redefinition of `LastContentFeedRSS` for articles only\n    \"\"\"\n    content_type = 'ARTICLE'\n    link = '/articles/'\n    title = u'Articles sur {}'.format(settings.ZDS_APP['site']['litteral_name'])\n    description = u'Les derniers articles parus sur {}.'.format(settings.ZDS_APP['site']['litteral_name'])\n\n\nclass LastArticlesFeedATOM(LastArticlesFeedRSS):\n    feed_type = Atom1Feed\n    subtitle = LastArticlesFeedRSS.description\n\n\nclass LastOpinionsFeedRSS(LastContentFeedRSS):\n    \"\"\"\n    Redefinition of `LastContentFeedRSS` for opinions only\n    \"\"\"\n    content_type = 'OPINION'\n    link = '/tribunes/'\n    title = u'Tribunes sur {}'.format(settings.ZDS_APP['site']['litteral_name'])\n    description = u'Les derniers billets des tribunes parus sur {}.'.format(\n        settings.ZDS_APP['site']['litteral_name'])\n\n\nclass LastOpinionsFeedATOM(LastOpinionsFeedRSS):\n    feed_type = Atom1Feed\n    subtitle = LastOpinionsFeedRSS.description\n", "path": "zds/tutorialv2/feeds.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n\nfrom django.conf import settings\nfrom django.db import models\nfrom django.db.models import Count, F\n\nfrom zds.utils.models import Tag\nfrom django.utils.translation import ugettext_lazy as _\n\n\nclass PublishedContentManager(models.Manager):\n    \"\"\"\n    Custom published content manager.\n    \"\"\"\n\n    def published_contents(self, _type=None):\n        \"\"\"\n        Get contents published order by date.\n\n        :return:\n        :rtype: django.db.models.QuerySet\n        \"\"\"\n        queryset = self.prefetch_related('content') \\\n            .prefetch_related('content__authors') \\\n            .prefetch_related('content__subcategory') \\\n            .filter(must_redirect=False) \\\n            .order_by('-publication_date')\n\n        if _type:\n            queryset = queryset.filter(content_type=_type)\n\n        return queryset\n\n    def last_contents_of_a_member_loaded(self, author, _type=None):\n        \"\"\"\n        Get contents published by author depends on settings.ZDS_APP['content']['user_page_number']\n\n        :param author:\n        :param _type: subtype to filter request\n        :return:\n        :rtype: django.db.models.QuerySet\n        \"\"\"\n        queryset = self.published_contents(_type) \\\n            .filter(content__authors__in=[author])\n\n        public_contents = queryset.all()[:settings.ZDS_APP['content']['user_page_number']]\n        return public_contents\n\n    def last_tutorials_of_a_member_loaded(self, author):\n        return self.last_contents_of_a_member_loaded(author, _type='TUTORIAL')\n\n    def last_articles_of_a_member_loaded(self, author):\n        return self.last_contents_of_a_member_loaded(author, _type='ARTICLE')\n\n    def last_opinions_of_a_member_loaded(self, author):\n        return self.last_contents_of_a_member_loaded(author, _type='OPINION')\n\n    def get_contents_count(self):\n        \"\"\"\n        :rtype: int\n        \"\"\"\n        return self.filter(must_redirect=False) \\\n                   .count()\n\n    def get_top_tags(self, displayed_types, limit=-1):\n        \"\"\"\n        Retrieve all most rated tags.\n\n        :param displayed_types:\n        :param limit: if ``-1``\u00a0or ``0`` => no limit. Else just takes the provided number of elements.\n        :return:\n        \"\"\"\n        published = self.filter(\n            must_redirect=False,\n            content__type__in=displayed_types).values('content__tags').distinct()\n        tags_pk = [tag['content__tags'] for tag in published]\n        queryset = Tag.objects\\\n            .filter(pk__in=tags_pk, publishablecontent__public_version__isnull=False,\n                    publishablecontent__type__in=displayed_types) \\\n            .annotate(num_content=Count('publishablecontent')) \\\n            .order_by('-num_content', 'title')\n        if limit > 0:\n            queryset = queryset[:limit]\n        return queryset\n\n    def transfer_paternity(self, unsubscribed_user, replacement_author):\n        \"\"\"\n        erase or transfer the paternity of all published content owned by a user.\n        if a content has more than one author, the unregistering author just leave its redaction\\\n        else just mark ``replacement_author`` as the new author\n\n        \"\"\"\n        for published in self.filter(authors__in=[unsubscribed_user]):\n            if published.authors.count() == 1:\n                published.authors.add(replacement_author)\n            published.authors.remove(unsubscribed_user)\n            published.save()\n\n\nclass PublishableContentManager(models.Manager):\n    \"\"\"...\"\"\"\n\n    def transfer_paternity(self, unregistered_user, replacement_author, gallery_class):\n        \"\"\"\n        Erases or transfers the paternity of all publishable content owned by a user. \\\n        If a content has more than one author, the unregistering author simply leaves its author list, \\\n        otherwise their published content are sent to ``replacement_author``, \\\n        unpublished content are deleted and their beta topics closed.\n\n        :param unregistered_user: the user to be unregistered\n        :param replacement_author: the new author\n        :param gallery_class: the class to link tutorial with gallery (perhaps overkill :p)\n        \"\"\"\n        for content in self.filter(authors__in=[unregistered_user]):\n            # we delete content only if not published with only one author\n            if not content.in_public() and content.authors.count() == 1:\n                if content.in_beta() and content.beta_topic:\n                    beta_topic = content.beta_topic\n                    beta_topic.is_locked = True\n                    beta_topic.save()\n                    first_post = beta_topic.first_post()\n                    first_post.update_content(_(u\"# Le tutoriel pr\u00e9sent\u00e9 par ce topic n'existe plus.\"))\n                    first_post.save()\n                content.delete()\n            else:\n                if content.authors.count() == 1:\n                    content.authors.add(replacement_author)\n                    external_gallery = gallery_class()\n                    external_gallery.user = replacement_author\n                    external_gallery.gallery = content.gallery\n                    external_gallery.mode = 'W'\n                    external_gallery.save()\n                    gallery_class.objects.filter(user=unregistered_user).filter(gallery=content.gallery).delete()\n\n                    content.authors.remove(unregistered_user)\n                    # we add a sentence to the content's introduction stating it was written by a former member.\n                    versioned = content.load_version()\n                    title = versioned.title\n                    introduction = _(u'[[i]]\\n|Ce contenu a \u00e9t\u00e9 r\u00e9dig\u00e9 par {} qui a quitt\u00e9 le site.\\n\\n')\\\n                        .format(unregistered_user.username) + versioned.get_introduction()\n                    conclusion = versioned.get_conclusion()\n                    sha = versioned.repo_update(title, introduction, conclusion,\n                                                commit_message='Author unsubscribed',\n                                                do_commit=True, update_slug=True)\n                    content.sha_draft = sha\n                    content.save()\n\n    def get_last_tutorials(self):\n        \"\"\"\n        This depends on settings.ZDS_APP['tutorial']['home_number'] parameter\n\n        :return: lit of last published content\n        :rtype: list\n        \"\"\"\n        home_number = settings.ZDS_APP['tutorial']['home_number']\n        all_contents = self.filter(type='TUTORIAL') \\\n                           .filter(public_version__isnull=False) \\\n                           .prefetch_related('authors') \\\n                           .prefetch_related('authors__profile') \\\n                           .select_related('last_note') \\\n                           .select_related('public_version') \\\n                           .prefetch_related('subcategory') \\\n                           .prefetch_related('tags') \\\n                           .order_by('-public_version__publication_date')[:home_number]\n        published = []\n        for content in all_contents:\n            content.public_version.content = content\n            published.append(content.public_version)\n        return published\n\n    def get_last_articles(self):\n        \"\"\"\n        ..attention:\n            this one uses a raw subquery for historical reasons. It will hopefully be replaced one day by an\n            ORM primitive.\n\n        :return: list of last articles expanded with 'count_note' property that prefetches number of comments\n        :rtype: list\n        \"\"\"\n        sub_query = 'SELECT COUNT(*) FROM {} WHERE {}={}'.format(\n            'tutorialv2_contentreaction',\n            'tutorialv2_contentreaction.related_content_id',\n            'tutorialv2_publishedcontent.content_pk',\n        )\n        home_number = settings.ZDS_APP['article']['home_number']\n        all_contents = self.filter(type='ARTICLE') \\\n                           .filter(public_version__isnull=False) \\\n                           .prefetch_related('authors') \\\n                           .prefetch_related('authors__profile') \\\n                           .select_related('last_note') \\\n                           .select_related('public_version') \\\n                           .prefetch_related('subcategory') \\\n                           .prefetch_related('tags') \\\n                           .extra(select={'count_note': sub_query}) \\\n                           .order_by('-public_version__publication_date')[:home_number]\n        published = []\n        for content in all_contents:\n            content.public_version.content = content\n            published.append(content.public_version)\n        return published\n\n    def get_last_opinions(self):\n        \"\"\"\n        This depends on settings.ZDS_APP['opinions']['home_number'] parameter.\n\n        :return: list of last opinions\n        :rtype: list\n        \"\"\"\n        home_number = settings.ZDS_APP['opinions']['home_number']\n        all_contents = self.filter(type='OPINION') \\\n                           .filter(public_version__isnull=False, sha_picked=F('sha_public')) \\\n                           .prefetch_related('authors') \\\n                           .prefetch_related('authors__profile') \\\n                           .select_related('last_note') \\\n                           .select_related('public_version') \\\n                           .prefetch_related('subcategory') \\\n                           .prefetch_related('tags') \\\n                           .order_by('-picked_date')[:home_number]\n        published = []\n        for content in all_contents:\n            content.public_version.content = content\n            published.append(content.public_version)\n        return published\n", "path": "zds/tutorialv2/managers.py"}, {"content": "# coding: utf-8\n\nfrom django.contrib.syndication.views import Feed\nfrom django.conf import settings\n\nfrom django.utils.feedgenerator import Atom1Feed\n\nfrom zds.tutorialv2.models.models_database import PublishedContent\nfrom zds.settings import ZDS_APP\n\n\nclass LastContentFeedRSS(Feed):\n    \"\"\"\n    RSS feed for any type of content.\n    \"\"\"\n    title = u'Contenus sur {}'.format(settings.ZDS_APP['site']['litteral_name'])\n    description = u'Les derniers contenus parus sur {}.'.format(settings.ZDS_APP['site']['litteral_name'])\n    link = ''\n    content_type = None\n\n    def items(self):\n        \"\"\"\n        :return: The last (typically 5) contents (sorted by publication date).\n        If `self.type` is not `None`, the contents will only be of this type.\n        \"\"\"\n        contents = PublishedContent.objects.published_contents(self.content_type)[:ZDS_APP['content']['feed_length']]\n\n        return contents\n\n    def item_title(self, item):\n        return item.content.title\n\n    def item_pubdate(self, item):\n        return item.publication_date\n\n    def item_description(self, item):\n        return item.content.description\n\n    def item_author_name(self, item):\n        authors_list = item.content.authors.all()\n        authors = []\n        for authors_obj in authors_list:\n            authors.append(authors_obj.username)\n        authors = ', '.join(authors)\n        return authors\n\n    def item_link(self, item):\n        return item.get_absolute_url_online()\n\n\nclass LastContentFeedATOM(LastContentFeedRSS):\n    feed_type = Atom1Feed\n    subtitle = LastContentFeedRSS.description\n\n\nclass LastTutorialsFeedRSS(LastContentFeedRSS):\n    \"\"\"\n    Redefinition of `LastContentFeedRSS` for tutorials only\n    \"\"\"\n    content_type = 'TUTORIAL'\n    link = '/tutoriels/'\n    title = u'Tutoriels sur {}'.format(settings.ZDS_APP['site']['litteral_name'])\n    description = u'Les derniers tutoriels parus sur {}.'.format(settings.ZDS_APP['site']['litteral_name'])\n\n\nclass LastTutorialsFeedATOM(LastTutorialsFeedRSS):\n    feed_type = Atom1Feed\n    subtitle = LastTutorialsFeedRSS.description\n\n\nclass LastArticlesFeedRSS(LastContentFeedRSS):\n    \"\"\"\n    Redefinition of `LastContentFeedRSS` for articles only\n    \"\"\"\n    content_type = 'ARTICLE'\n    link = '/articles/'\n    title = u'Articles sur {}'.format(settings.ZDS_APP['site']['litteral_name'])\n    description = u'Les derniers articles parus sur {}.'.format(settings.ZDS_APP['site']['litteral_name'])\n\n\nclass LastArticlesFeedATOM(LastArticlesFeedRSS):\n    feed_type = Atom1Feed\n    subtitle = LastArticlesFeedRSS.description\n\n\nclass LastOpinionsFeedRSS(LastContentFeedRSS):\n    \"\"\"\n    Redefinition of `LastContentFeedRSS` for opinions only\n    \"\"\"\n    content_type = 'OPINION'\n    link = '/tribunes/'\n    title = u'Tribunes sur {}'.format(settings.ZDS_APP['site']['litteral_name'])\n    description = u'Les derniers billets des tribunes parus sur {}.'.format(\n        settings.ZDS_APP['site']['litteral_name'])\n\n\nclass LastOpinionsFeedATOM(LastOpinionsFeedRSS):\n    feed_type = Atom1Feed\n    subtitle = LastOpinionsFeedRSS.description\n", "path": "zds/tutorialv2/feeds.py"}]}