Repository: zestedesavoir/zds-site

Issue:
En mode connecté, on fait une requête pour CHAQUE MP RECU !
Quand on est connecté, on passe par ce bout de code sur **toutes** les pages :

zds-site/templates/base.html ligne 258 : `{% with topics=user|interventions_privatetopics %}`

Il fait cette requête pour **chaque MP que vous avez reçu** !

```
SELECT `mp_privatetopic`.`id`, `mp_privatetopic`.`title`, `mp_privatetopic`.`subtitle`, `mp_privatetopic`.`author_id`, `mp_privatetopic`.`last_message_id`, `mp_privatetopic`.`pubdate` FROM `mp_privatetopic` WHERE `mp_privatetopic`.`id` = <id membre>
```

C'est à corriger d'urgence. Ça passe dans la v1.5.

Et après ça on s'étonne que certaines personnes trouvaient le site lent...



Discussion:
J'ai  MAJ la première version (mauvaise interprétation) avec la triste réalité...

... et c'est là que j'ai une bonne raison de râler pour les commentaires : le problème vient de templatetags/interventions.py, méthode `def interventions_privatetopics(user):`.

Qui fait des trucs dégueulasses sans le moindre commentaire. Là où ça aurait couté 2 minutes de mettre 2 lignes de commentaires pour expliquer comment ce truc fonctionne, je passe 2 heures à essayer de le comprendre.


Resolving patch:
diff --git a/zds/utils/templatetags/interventions.py b/zds/utils/templatetags/interventions.py
--- a/zds/utils/templatetags/interventions.py
+++ b/zds/utils/templatetags/interventions.py
@@ -4,11 +4,11 @@
 import time
 
 from django import template
-from django.db.models import Q, F
+from django.db.models import F
 
 from zds.article.models import Reaction, ArticleRead
 from zds.forum.models import TopicFollowed, never_read as never_read_topic, Post, TopicRead
-from zds.mp.models import PrivateTopic, PrivateTopicRead
+from zds.mp.models import PrivateTopic
 from zds.tutorial.models import Note, TutorialRead
 from zds.utils.models import Alert
 
@@ -131,22 +131,21 @@ def interventions_topics(user):
 @register.filter('interventions_privatetopics')
 def interventions_privatetopics(user):
 
-    topics_never_read = list(PrivateTopicRead.objects
-                             .filter(user=user)
-                             .filter(privatepost=F('privatetopic__last_message')).all())
-
-    tnrs = []
-    for tnr in topics_never_read:
-        tnrs.append(tnr.privatetopic.pk)
-
-    privatetopics_unread = PrivateTopic.objects\
-        .filter(Q(author=user) | Q(participants__in=[user]))\
-        .exclude(pk__in=tnrs)\
-        .select_related("privatetopic")\
-        .order_by("-pubdate")\
-        .distinct()
-
-    return {'unread': privatetopics_unread}
+    # Raw query because ORM doesn't seems to allow this kind of "left outer join" clauses.
+    # Parameters = list with 3x the same ID because SQLite backend doesn't allow map parameters.
+    privatetopics_unread = PrivateTopic.objects.raw(
+        '''
+        select distinct t.*
+        from mp_privatetopic t
+        inner join mp_privatetopic_participants p on p.privatetopic_id = t.id
+        left outer join mp_privatetopicread r on r.user_id = %s and r.privatepost_id = t.last_message_id
+        where (t.author_id = %s or p.user_id = %s)
+          and r.id is null
+        order by t.pubdate desc''',
+        [user.id, user.id, user.id])
+
+    # "total" re-do the query, but there is no other way to get the length as __len__ is not available on raw queries.
+    return {'unread': privatetopics_unread, 'total': len(list(privatetopics_unread))}
 
 
 @register.filter(name='alerts_list')


Test patch: