Repository: zestedesavoir/zds-site

Issue:
Incohérence dans le nombre de contenus spécifié pour un tag
Serveur : Bêta
Version : v18-RC3/ffa18f8
Système : Mac OS X El Capitain
Navigateur : Safari Version 9.0.3 (11601.4.4)

Scénario :
- Rendez-vous sur la [liste des tags](https://beta.zestedesavoir.com/contenus/tags/).
- Prenons comme exemple la catégorie "cds" et constatez 25 contenus spécifiés.
- Cliquez sur le tag et constatez qu'il n'y a que 16 contenus.



Discussion:
Je crois qu'il s'agit du même type d'erreur que dans  #3493 : [ici, on oublie le `redirect=False`](https://github.com/zestedesavoir/zds-site/blob/dev/zds/tutorialv2/views/views_published.py#L675) :)

(non, c'est un peu en dessous, mais bref, c'est l'idée)

@pierre-24 : c'est quoi cette histoire de redirect ? Ça sert à quoi ?

Une autre question, on a quelque chose d'assez grave sur la beta : 

```
>>> PublishedContent.objects.filter(content_public_slug="les-promesses-en-javascript")                                       
[<PublishedContent: Version publique de "Les promesses en JavaScript">, <PublishedContent: Version publique de "Les promesses
en JavaScript">]                                                                                                             
```

Pas de panique, c'est normal :)

[C'est en fait `must_redirect`](https://github.com/zestedesavoir/zds-site/blob/dev/zds/tutorialv2/models/models_database.py#L574) (_my bad_).

Ben en fait, quand on a annoncé qu'on cassait le SEO, on c'est fait démonter en bonne et due forme. Du coup, pour éviter les ennuis, on a mis ce machin là en place pour les tutos qui ont été créé avant la ZEP-12.
1. Avant la ZEP-12,  article et tutos étaient séparés dans des tables distinctes, avec un `pk` donné ;
2. Forcément, comme ont a remis tout dans la même table, les `pk` ne correspondaient plus (mais le slug restait le même) ;
3. Du coup, on a rajouté cette astuce là, avec un objet en `must_redirect=True` qui contient l'ancien `pk` (avant ZEP-12) et "redirige" sur le nouvel objet (en `must_redirect=False` et avec le bon pk). Ça vaut ce que ça vaut.
4. Cette astuce sert aussi quand le slug d'un contenu change entre deux publications (exemple typique, un article est renommé pour des causes éthiques).

Du coup, les `PublishedContent` existent en plusieurs exemplaire pour un contenu donné (tous pointent sur le même `PublishableContent`, évidement), mais il n'y en a qu'un seul qui a `must_redirect=False` et qui correspond à la dernière version publiée en date. Et il faut tenir compte de ça, évidement :)

Merci @pierre-24, je corrige ça de suite.


Resolving patch:
diff --git a/zds/tutorialv2/urls/urls_articles.py b/zds/tutorialv2/urls/urls_articles.py
--- a/zds/tutorialv2/urls/urls_articles.py
+++ b/zds/tutorialv2/urls/urls_articles.py
@@ -2,7 +2,8 @@
 
 from django.conf.urls import url
 
-from zds.tutorialv2.views.views_published import ListArticles, DisplayOnlineArticle, DownloadOnlineArticle
+from zds.tutorialv2.views.views_published import ListArticles, DisplayOnlineArticle, DownloadOnlineArticle, \
+    TagsListView
 from zds.tutorialv2.feeds import LastArticlesFeedRSS, LastArticlesFeedATOM
 
 urlpatterns = [
@@ -25,5 +26,6 @@
         name='download-zip'),
 
     # Listing
-    url(r'^$', ListArticles.as_view(), name='list')
+    url(r'^$', ListArticles.as_view(), name='list'),
+    url(r'tags/*', TagsListView.as_view(displayed_types=["ARTICLE"]), name="tags")
 ]
diff --git a/zds/tutorialv2/urls/urls_tutorials.py b/zds/tutorialv2/urls/urls_tutorials.py
--- a/zds/tutorialv2/urls/urls_tutorials.py
+++ b/zds/tutorialv2/urls/urls_tutorials.py
@@ -4,9 +4,10 @@
 from zds.tutorialv2.views.views_contents import RedirectOldBetaTuto
 
 from zds.tutorialv2.views.views_published import ListTutorials, DisplayOnlineTutorial, DisplayOnlineContainer, \
-    DownloadOnlineTutorial, RedirectContentSEO
+    DownloadOnlineTutorial, RedirectContentSEO, TagsListView
 from zds.tutorialv2.feeds import LastTutorialsFeedRSS, LastTutorialsFeedATOM
 
+
 urlpatterns = [
     # flux
     url(r'^flux/rss/$', LastTutorialsFeedRSS(), name='feed-rss'),
@@ -40,5 +41,6 @@
     url('^beta/(?P<pk>\d+)/(?P<slug>.+)', RedirectOldBetaTuto.as_view(), name="old-beta-url"),
 
     # Listing
-    url(r'^$', ListTutorials.as_view(), name='list')
+    url(r'^$', ListTutorials.as_view(), name='list'),
+    url(r'tags/$', TagsListView.as_view(displayed_types=["TUTORIAL"]), name="tags")
 ]
diff --git a/zds/tutorialv2/views/views_published.py b/zds/tutorialv2/views/views_published.py
--- a/zds/tutorialv2/views/views_published.py
+++ b/zds/tutorialv2/views/views_published.py
@@ -671,11 +671,16 @@ class TagsListView(ListView):
     model = Tag
     template_name = "tutorialv2/view/tags.html"
     context_object_name = 'tags'
+    displayed_types = ["TUTORIAL", "ARTICLE"]
 
     def get_queryset(self):
-        tags_pk = [tag['content__tags'] for tag in PublishedContent.objects.values('content__tags').distinct()]
+        published = PublishedContent.objects.filter(
+            must_redirect=False,
+            content__type__in=self.displayed_types).values('content__tags').distinct()
+        tags_pk = [tag['content__tags'] for tag in published]
         queryset = Tag.objects\
-            .filter(pk__in=tags_pk)\
-            .annotate(num_content=Count('publishablecontent__publishedcontent'))\
+            .filter(pk__in=tags_pk, publishablecontent__public_version__isnull=False,
+                    publishablecontent__type__in=self.displayed_types)\
+            .annotate(num_content=Count('publishablecontent'))\
             .order_by('-num_content', 'title')
         return queryset


Test patch: