Repository: zestedesavoir/zds-site

Issue:
[beta] La liste des sujets suivis n'est pas cohérente avec la réalité
Url incriminée : https://beta.zestedesavoir.com/forums/notifications/

Comme en témoigne le screen ci-dessous, lorsque j'ai un sujet suivis que je n'ai pas encore lu, dans la sidebar le gras est visible et montre que le topic n'est pas lu, mais dans la liste qui s'affiche on a pas de graisse pour différencier les topic lu ou non.

![graisser](https://cloud.githubusercontent.com/assets/6066015/8455104/7357f176-2002-11e5-9894-4240f4d20d77.PNG)

Vu que ça marche bien en prod, j'en déduis qu'on tiens une regression.



Discussion:
Voilà :

![](http://recette3.supertoinette.com/49241/thumb/800/-/49241.jpg)

Haha, you made my day :P

Du coup tu as bien fait de tagguer en "ré-graisse-ion" ;)

:P 

Et sinon, le bug est aussi visible dans la liste des sujets d'un topic.

Ça m'a l'air lié à #2785 ! Ping @artragis ;)

nope, je ne touche pas à cette page là. C'est plutôt le refacto des forums qui a possiblement été cassé.

Si, [tu touches au `topic_row.part.html`](https://github.com/zestedesavoir/zds-site/commits/dev/templates/forum/includes/topic_row.part.html) et plus précisément à [la condition `if` qui met en "unread" ou pas le topic](https://github.com/zestedesavoir/zds-site/blame/dev/templates/forum/includes/topic_row.part.html#L8) !

c'est bon, j'ai vu pourquoi !. Je fais une PR ce midi.

2015-07-02 11:46 GMT+02:00 Situphen notifications@github.com:

> Si, tu touches au topic_row.part.html
> https://github.com/zestedesavoir/zds-site/commits/dev/templates/forum/includes/topic_row.part.html
> et plus précisément à la condition if qui met en "unread" ou pas le topic
> https://github.com/zestedesavoir/zds-site/blame/dev/templates/forum/includes/topic_row.part.html#L8
> !
> 
> —
> Reply to this email directly or view it on GitHub
> https://github.com/zestedesavoir/zds-site/issues/2873#issuecomment-117981330
> .

PR [faite](https://github.com/zestedesavoir/zds-site/pull/2880) et j'ai même fait ça en mode TDD (i.e le teste fail, je développe, le test passe).

Et PR mergée, merci @artragis :)

mais de rien pierre :p

Le 04/07/2015 10:47, Pierre Beaujean a écrit :

> Closed #2873 https://github.com/zestedesavoir/zds-site/issues/2873.
> 
> —
> Reply to this email directly or view it on GitHub 
> https://github.com/zestedesavoir/zds-site/issues/2873#event-347756875.

C'est absolument pas corrigé, et même plus large que ça : sur les forums, **je n'ai aucun sujet en gras**.

C'est le genre de gag qui va mériter un hotfix...

PS : Je dégage le tag "facile" puisque de toute évidence ce n'est pas le cas.

Apparemment le problème n'a été corrigé que dans la page des notifications alors qu'il était présent partout dans les forums.

J'avais prévenu que c'était possible. J'avais demandé à ce que ça soit 
vérifié, ça ne l'a pas été. Le problème c'est que là, je ne comprends 
pas pourquoi ça fait ça puisque le test unitaire fonctionne et donne des 
résultats cohérents.

Le 05/07/2015 01:14, SpaceFox a écrit :

> Apparemment le problème n'a été corrigé que dans la page des 
> notifications alors qu'il était présent partout dans les forums.
> 
> —
> Reply to this email directly or view it on GitHub 
> https://github.com/zestedesavoir/zds-site/issues/2873#issuecomment-118561774.

Ce à quoi je répond "qu'est ce que _what the fuck_", quand j'ai fait la QA ça marchait nickel (même la liste des forums). Là, on dirait que la PR n'a eu absolument aucun effet, puisque rien ne s'est remis en gras.

D'AILLEURS !

Lorsque je _checkout_ (oui, c'est aussi mal que _fix_) la branche d'artragis correspondant à la PR, j'ai bel et bien du gras là ou je devrait.

Liste des notifs:

![screenshot from 2015-07-05 08 45 13](https://cloud.githubusercontent.com/assets/7889675/8510603/4d22c722-22f2-11e5-8f8a-992c754582ca.png)

Liste des forums:

![screenshot from 2015-07-05 08 46 44](https://cloud.githubusercontent.com/assets/7889675/8510604/6998fe26-22f2-11e5-9efd-6ffefa7690f0.png)

Alors désolé, cette PR fonctionnait TRÈS BIEN, le problème se situe ailleurs. Non mais.

Ouf ! car là je comprenais pas.

Le 05/07/2015 08:48, Pierre Beaujean a écrit :

> Ce à quoi je répond "qu'est ce que /what the fuck/", quand j'ai fait 
> la QA ça marchait nickel (même la liste des forums). Là, on dirait que 
> la PR n'a eu absolument aucun effet, puisque rien ne s'est remis en gras.
> 
> D'AILLEURS !
> 
> Lorsque je /checkout/ (oui, c'est aussi mal que /fix/) la branche 
> d'artragis correspondant à la PR, j'ai bel et bien du gras là ou je 
> devrait.
> 
> Liste des notifs:
> 
> screenshot from 2015-07-05 08 45 13 
> https://cloud.githubusercontent.com/assets/7889675/8510603/4d22c722-22f2-11e5-8f8a-992c754582ca.png
> 
> Liste des forums:
> 
> screenshot from 2015-07-05 08 46 44 
> https://cloud.githubusercontent.com/assets/7889675/8510604/6998fe26-22f2-11e5-9efd-6ffefa7690f0.png
> 
> Alors désolé, cette PR fonctionnait TRÈS BIEN, le problème se situe 
> ailleurs. Non mais.
> 
> —
> Reply to this email directly or view it on GitHub 
> https://github.com/zestedesavoir/zds-site/issues/2873#issuecomment-118588361.

Du coup, à priori, le hotfix revient à prendre la branche d'atragis et à la ré-appliquer sur _prod_, c'est probablement aussi simple que ça.

avant, il faudrait détecter la différence entre ma branche et la prod.

Le 05/07/2015 08:54, Pierre Beaujean a écrit :

> Du coup, à priori, le hotfix revient à prendre la branche d'atragis et 
> à la ré-appliquer sur /prod/, c'est probablement aussi simple que ça.
> 
> —
> Reply to this email directly or view it on GitHub 
> https://github.com/zestedesavoir/zds-site/issues/2873#issuecomment-118588476.

Je trouve pas, mais peut-être que c'est plus pervers que ça. En effet, quelque sois la branche (donc _prod_ aussi), j'ai bien du gras quand
- Je suis sensé avoir une notif sur le sujet en question : 

![screenshot from 2015-07-05 09 38 19](https://cloud.githubusercontent.com/assets/7889675/8510758/97cab2a6-22f9-11e5-8e1e-ba416443d47d.png)
- Il y a un nouveau sujet que je n'ai jamais lu : 

![screenshot from 2015-07-05 09 38 51](https://cloud.githubusercontent.com/assets/7889675/8510759/ac184412-22f9-11e5-93de-a9d4ddb835a0.png)

Donc à mon avis, on se tape quelque chose de plus pervers que ça (mais je sais pas quoi). Quelqu'un peu pas aller générer une notif sur le forum ?

j'ai la vague impressionq ue notre problème de https empêche à la 
condition is_authenticated d'être validée.

Le 05/07/2015 09:39, Pierre Beaujean a écrit :

> Je trouve pas, mais peut-être que c'est plus pervers que ça. En effet, 
> quelque sois la branche (donc /prod/ aussi), j'ai bien du gras quand
> - Je suis sensé avoir une notif sur le sujet en question :
> 
> screenshot from 2015-07-05 09 38 19 
> https://cloud.githubusercontent.com/assets/7889675/8510758/97cab2a6-22f9-11e5-8e1e-ba416443d47d.png
> - Il y a un nouveau sujet que je n'ai jamais lu :
> 
> screenshot from 2015-07-05 09 38 51 
> https://cloud.githubusercontent.com/assets/7889675/8510759/ac184412-22f9-11e5-93de-a9d4ddb835a0.png
> 
> Donc à mon avis, on se tape quelque chose de plus pervers que ça (mais 
> je sais pas quoi). Quelqu'un peu pas aller générer une notif sur le 
> forum ?
> 
> —
> Reply to this email directly or view it on GitHub 
> https://github.com/zestedesavoir/zds-site/issues/2873#issuecomment-118592284.

Bien essayé, mais vu qu'on a un souci de certif', je navigue en HTTP pour le moment, et j'ai bien pas de gras sur le site. À moins que ça ne soit quand même lié.

tu arrives à être en http ET authentifié?

Le 05/07/2015 09:42, Pierre Beaujean a écrit :

> Bien essayé, mais vu qu'on a un souci de certif', je navigue en HTTP 
> pour le moment, et j'ai bien pas de gras sur le site. À moins que ça 
> ne soit quand même lié.
> 
> —
> Reply to this email directly or view it on GitHub 
> https://github.com/zestedesavoir/zds-site/issues/2873#issuecomment-118593128.

~~Comme tu peux le voir:~~ voir message après.

![screenshot from 2015-07-05 09 43 36](https://cloud.githubusercontent.com/assets/7889675/8510772/536689e0-22fa-11e5-9498-9337c9c03a3d.png)

(tu peux aussi constater que ta notif' ne m'as pas généré de gras)

EDIT: mauvais screen :p 

![screenshot from 2015-07-05 09 44 53](https://cloud.githubusercontent.com/assets/7889675/8510775/86c73870-22fa-11e5-82f7-779eec4e240b.png)

Par contre dans la page "toutes les notifs" on est ok?

Le 05/07/2015 09:44, Pierre Beaujean a écrit :

> Comme tu peux le voir:
> 
> screenshot from 2015-07-05 09 43 36 
> https://cloud.githubusercontent.com/assets/7889675/8510772/536689e0-22fa-11e5-9498-9337c9c03a3d.png
> 
> (tu peux aussi constater que ta notif' ne m'as pas généré de gras)
> 
> —
> Reply to this email directly or view it on GitHub 
> https://github.com/zestedesavoir/zds-site/issues/2873#issuecomment-118593462.

Ça attendra la prochaine notif', j'ai cliqué :p 

Ça le fait effectivement sur la liste des notifs':

![screenshot from 2015-07-05 10 16 08](https://cloud.githubusercontent.com/assets/7889675/8510881/e47bddf0-22fe-11e5-864b-ce08cf64a379.png)

(donc reste à comprendre pourquoi ça le fait en local et pas ici)

Aller, l'histoire de bien en rajouter: la bêta est _iso_-prod, son certif' HTTPS est valide et correct et ça bugge quand même. Par acquis de conscience, j'ai essayé de regénérer le _front_, et c'est pas ça non plus.  Fait ch***

si tu as les droits sur la beta, peux-tu temporairement mettre le 
"debug" à True histoire qu'on ait un log des requêtes.

Le 05/07/2015 11:03, Pierre Beaujean a écrit :

> Aller, l'histoire de bien en rajouter: la bêta est /iso/-prod, son 
> certif' HTTPS est valide et correct et ça bugge quand même. Par acquis 
> de conscience, j'ai essayé de regénérer le /front/, et c'est pas ça 
> non plus. Fait ch***
> 
> —
> Reply to this email directly or view it on GitHub 
> https://github.com/zestedesavoir/zds-site/issues/2873#issuecomment-118596976.

Je n'ai pas ce plaisir ;)

> si tu as les droits sur la beta, peux-tu temporairement mettre le
> "debug" à True histoire qu'on ait un log des requêtes.

Je peux le faire ; aussi, c'est sûr que c'est pas un problèmes front, puisque les éléments ont simplement pas la classe `.unread`

oui, c'est pour ça que je veux voir les requêtes.

Le 05/07/2015 11:18, Sandhose a écrit :

> ```
> si tu as les droits sur la beta, peux-tu temporairement mettre le
> "debug" à True histoire qu'on ait un log des requêtes.
> ```
> 
> Je peux le faire ; aussi, c'est sûr que c'est pas un problèmes front, 
> puisque les éléments ont simplement pas la classe |.unread|
> 
> —
> Reply to this email directly or view it on GitHub 
> https://github.com/zestedesavoir/zds-site/issues/2873#issuecomment-118601515.

Merci, là j'ai juste un problème : ce salop n'envoie pas la requête. il 
fait juste ça :

```
/opt/zdsenv/bin/gunicorn  in<module>(9)
   load_entry_point('gunicorn==19.3.0', 'console_scripts', 'gunicorn')()
/opt/zdsenv/local/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py  inrun(74)
   WSGIApplication("%(prog)s [OPTIONS] [APP_MODULE]").run()
/opt/zdsenv/local/lib/python2.7/site-packages/gunicorn/app/base.py  inrun(189)
   super(Application, self).run()
/opt/zdsenv/local/lib/python2.7/site-packages/gunicorn/app/base.py  inrun(72)
   Arbiter(self).run()
/opt/zdsenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py  inrun(174)
   self.manage_workers()
/opt/zdsenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py  inmanage_workers(477)
   self.spawn_workers()
/opt/zdsenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py  inspawn_workers(540)
   self.spawn_worker()
/opt/zdsenv/local/lib/python2.7/site-packages/gunicorn/arbiter.py  inspawn_worker(507)
   worker.init_process()
/opt/zdsenv/local/lib/python2.7/site-packages/gunicorn/workers/base.py  ininit_process(124)
   self.run()
/opt/zdsenv/local/lib/python2.7/site-packages/gunicorn/workers/sync.py  inrun(119)
   self.run_for_one(timeout)
/opt/zdsenv/local/lib/python2.7/site-packages/gunicorn/workers/sync.py  inrun_for_one(66)
   self.accept(listener)
/opt/zdsenv/local/lib/python2.7/site-packages/gunicorn/workers/sync.py  inaccept(30)
   self.handle(listener, client, addr)
/opt/zdsenv/local/lib/python2.7/site-packages/gunicorn/workers/sync.py  inhandle(130)
   self.handle_request(listener, req, client, addr)
/opt/zdsenv/local/lib/python2.7/site-packages/gunicorn/workers/sync.py  inhandle_request(171)
   respiter = self.wsgi(environ, resp.start_response)
/opt/zdsenv/ZesteDeSavoir/zds/forum/views.py  inget(73)
   return super(ForumTopicsListView, self).get(request, *args, **kwargs)
/opt/zdsenv/ZesteDeSavoir/zds/forum/views.py  inget_context_data(82)
   'topic_read': TopicRead.objects.list_read_topic_pk(self.request.user, context['topics'])
/opt/zdsenv/ZesteDeSavoir/zds/forum/managers.py  inlist_read_topic_pk(110)
   return self.topic_read_by_user(user, topic_sub_list).values_list('topic__pk', flat=True)
/opt/zdsenv/ZesteDeSavoir/zds/forum/managers.py  intopic_read_by_user(102)
   base_query_set = self.filter(user__pk=user.pk)
```

ce qui génère la requête

```
*SELECT*   `auth_user`.`id`,
  `auth_user`.`password`, `auth_user`.`last_login`,
`auth_user`.`is_superuser`, `auth_user`.`username`,
`auth_user`.`first_name`, `auth_user`.`last_name`, `auth_user`.`email`,
`auth_user`.`is_staff`, `auth_user`.`is_active`,
`auth_user`.`date_joined`  <https://beta.zestedesavoir.com/forums/communaute/dev-zone/#>  *FROM*  `auth_user`*WHERE*  `auth_user`.`id` = 82*LIMIT*  21
```

c'est vraiment mystique là.

Le 05/07/2015 11:18, Sandhose a écrit :

> ```
> si tu as les droits sur la beta, peux-tu temporairement mettre le
> "debug" à True histoire qu'on ait un log des requêtes.
> ```
> 
> Je peux le faire ; aussi, c'est sûr que c'est pas un problèmes front, 
> puisque les éléments ont simplement pas la classe |.unread|
> 
> —
> Reply to this email directly or view it on GitHub 
> https://github.com/zestedesavoir/zds-site/issues/2873#issuecomment-118601515.

Attend, j'essaye de comprendre, c'est quoi le problème, là ?

Il passe pas non plus par `{% if user.is_authenticated and topic.pk in topic_read %}` de [topic_row.part.html](https://github.com/zestedesavoir/zds-site/blob/dev/templates/forum/includes/topic_row.part.html) dans lequel il est censé passer pour rajouter le `unread` qui va bien.

Est ce qu'on serait pas sur ce genre de bug un peu ennuyeux mysql/sqlite ?

il ne lance pas la requête qui sélectionne tous les topics lus.

ce qui d'ailleurs me casse les pieds puisque du coup théoriquement 
"topic_read" devrait être vide et donc TOUS les topics devraient être 
marqués "non lus" et non "lus".

Mystique.

Le 05/07/2015 11:51, Pierre Beaujean a écrit :

> Attend, j'essaye de comprendre, c'est quoi le problème, là ?
> 
> —
> Reply to this email directly or view it on GitHub 
> https://github.com/zestedesavoir/zds-site/issues/2873#issuecomment-118604067.

> Est ce qu'on serait pas sur ce genre de bug un peu ennuyeux mysql/sqlite ?

c'est pas impossible.

Le 05/07/2015 11:57, Pierre Beaujean a écrit :

> Est ce qu'on serait pas sur ce genre de bug un peu ennuyeux mysql/sqlite ?

Grâce à @artragis, on a pu confirmer qu'il s'agissait bien d'un de ces bugs retords qui apparaissent quand on commence à employer mysql alors que ça fonctionne très bien en local avec sqlite.

>_<

Donc je fait des test avec MySQL. Et j'ai trouvé un truc intéressant/débile.

La fonction [`topic_read_by_user()`](https://github.com/zestedesavoir/zds-site/blob/dev/zds/forum/managers.py#L100) prend en paramètre une liste de sujet, `topic_sub_list`. Si `topic_sub_list` est de type `list`, tout va très bien (c'est le cas pour la liste des notifs, parc'e que ça sort du paginateur). Si `topic_sub_list` est un `QuerySet`, alors c'est le bazar, et ça fini en 

```
1235 -- This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery
```

(je parie que le log Django en est rempli, du coup).

Le fix est complètement idiot: `topic_sub_list=[i for i in quesryset]`. Et il semblerai que les performances soient pas impactées/améliorées. _brace yourself, fix is coming_ !

ou bien simplement ".all()"

Le 05/07/2015 14:50, Pierre Beaujean a écrit :

> Donc je fait des test avec MySQL. Et j'ai trouvé un truc 
> intéressant/débile.
> 
> La fonction |topic_read_by_user()| 
> https://github.com/zestedesavoir/zds-site/blob/dev/zds/forum/managers.py#L100 
> prend en paramètre une liste de sujet, |topic_sub_list|. Si 
> |topic_sub_list| est de type |list|, tout va très bien (c'est le cas 
> pour la liste des notifs, parc'e que ça sort du paginateur). Si 
> |topic_sub_list| est un |QuerySet|, alors c'est le bazar, et ça fini en
> 
> |1235 -- This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery
> |
> 
> (je parie que le log Django en est rempli, du coup).
> 
> Le fix est complètement idiot: |topic_sub_list=[i for i in 
> quesryset]|. Et il semblerai que les performances soient pas 
> impactées/améliorées. /brace yourself, fix is coming/ !
> 
> —
> Reply to this email directly or view it on GitHub 
> https://github.com/zestedesavoir/zds-site/issues/2873#issuecomment-118618631.


Resolving patch:
diff --git a/zds/forum/managers.py b/zds/forum/managers.py
--- a/zds/forum/managers.py
+++ b/zds/forum/managers.py
@@ -98,7 +98,14 @@ def get_all_messages_of_a_user(self, current, target):
 class TopicReadManager(models.Manager):
 
     def topic_read_by_user(self, user, topic_sub_list=None):
+        """ get all the topic that the user has already read.
 
+        :param user: an authenticated user
+        :param topic_sub_list: optional list of topics. If not ``None`` no subject out of this list will be selected
+        :type topic_sub_list: list
+        :return: the queryset over the already read topics
+        :rtype: QuerySet
+        """
         base_query_set = self.filter(user__pk=user.pk)
         if topic_sub_list is not None:
             base_query_set = base_query_set.filter(topic__in=topic_sub_list)
@@ -107,4 +114,12 @@ def topic_read_by_user(self, user, topic_sub_list=None):
         return base_query_set
 
     def list_read_topic_pk(self, user, topic_sub_list=None):
+        """ get all the topic that the user has already read in a flat list.
+
+        :param user: an authenticated user
+        :param topic_sub_list: optional list of topics. If not ``None`` no subject out of this list will be selected
+        :type topic_sub_list: list
+        :return: the flat list of all topics primary key
+        :rtype: list
+        """
         return self.topic_read_by_user(user, topic_sub_list).values_list('topic__pk', flat=True)
diff --git a/zds/forum/views.py b/zds/forum/views.py
--- a/zds/forum/views.py
+++ b/zds/forum/views.py
@@ -74,6 +74,9 @@ def get(self, request, *args, **kwargs):
 
     def get_context_data(self, **kwargs):
         context = super(ForumTopicsListView, self).get_context_data(**kwargs)
+        context['topics'] = list(context['topics'].all())
+        # we need to load it in memory because later we will get the
+        # "already read topic" set out of this list and MySQL does not support that type of subquery
         context.update({
             'forum': self.object,
             'sticky_topics': self.filter_queryset(
@@ -84,7 +87,13 @@ def get_context_data(self, **kwargs):
         return context
 
     def get_object(self, queryset=None):
-        return get_object_or_404(Forum, slug=self.kwargs.get('forum_slug'))
+        forum = Forum.objects\
+                     .select_related('category')\
+                     .filter(slug=self.kwargs.get('forum_slug'))\
+                     .first()
+        if forum is None:
+            raise Http404("Forum with slug {} was not found".format(self.kwargs.get('forum_slug')))
+        return forum
 
     def get_queryset(self):
         self.queryset = Topic.objects.get_all_topics_of_a_forum(self.object.pk)
@@ -354,6 +363,9 @@ def get(self, request, *args, **kwargs):
 
     def get_context_data(self, *args, **kwargs):
         context = super(FindTopicByTag, self).get_context_data(*args, **kwargs)
+        context['topics'] = list(context['topics'].all())
+        # we need to load it in memory because later we will get the
+        # "already read topic" set out of this list and MySQL does not support that type of subquery
         context.update({
             'tag': self.object,
             'topic_read': TopicRead.objects.list_read_topic_pk(self.request.user, context['topics'])
diff --git a/zds/member/views.py b/zds/member/views.py
--- a/zds/member/views.py
+++ b/zds/member/views.py
@@ -74,14 +74,14 @@ def get_context_data(self, **kwargs):
         usr = context['usr']
         profile = usr.profile
         context['profile'] = profile
-        context['topics'] = Topic.objects.last_topics_of_a_member(usr, self.request.user)
+        context['topics'] = list(Topic.objects.last_topics_of_a_member(usr, self.request.user))
         context['articles'] = Article.objects.last_articles_of_a_member_loaded(usr)
         context['tutorials'] = Tutorial.objects.last_tutorials_of_a_member_loaded(usr)
         context['old_tutos'] = Profile.objects.all_old_tutos_from_site_du_zero(profile)
         context['karmanotes'] = KarmaNote.objects.filter(user=usr).order_by('-create_at')
         context['karmaform'] = KarmaForm(profile)
         context['form'] = OldTutoForm(profile)
-        context['topic_read'] = TopicRead.objects.list_read_topic_pk(usr, context['topics'])
+        context['topic_read'] = TopicRead.objects.list_read_topic_pk(self.request.user, context['topics'])
         return context
 
 


Test patch: