Django annotate : à quoi ça sert ?
Je n’avais pas bien compris l’utilité de « annotate » dans les queries Django jusqu’à maintenant…
Voici quel était mon problème :
J’avais un modèle de base, Activite
. Une activité contenait des choses concernant… une activité. Si si je vous jure !
Par exemple, une activité consistait à ajouter un voyage. Ou avoir une nouvelle relation. Ou faire un témoignage comme quoi on aimait bien le site. Etc.
Je voulais que ces activités soient « partageables » entre les amis.
J’ai crée un modèles ActiviteShare
. Facile jusque là.
Mais lorsque je demandais à récupérer toutes les activités, il fallait que je les trie en me basant sur le fait de savoir si elles étaient partagées. Pour exagérer, imaginons une activité qui était faite en 2010. Vous étiez parti à Malibu. Génial ! Et maintenant, en 2016, un ami s’inscrit, devient votre ami, et vous voulez partager cette activité avec lui. Il faut qu’elle s’affiche dans votre mur, comme activité « partagée récemment », mais qu’elle garde sa date de 2010, ok ?
Donc je devais trier d’abord en fonction de la date de ActiviteShare
puis seulement après par la date de création de l’Activite
.
Seul hic : si vous aviez partagé cette activité avec 10 contacts, au moment du tri, Django renvoyait dix fois le même enregistrement.
Mon tri était super basique, du genre :
Activite.objects.filter(
# blabla
).order_by(
'-activiteshared__date_last_modif',
'-date_last_modif',
'-date_publication',)
Mais ça ne marchait pas. 🙁
La solution ? Annotate.
Pour vous expliquer avant de mettre le code : je lui demande, lors de la requête, de garder la date maximale parmi toutes les dates partagées, et de l’appeler « mx ». Ensuite, je demande de trier simplement d’abord par « mx », puis par la date de dernière modification de l’activité.
Activite.objects.filter(
# blabla
).annotate(mx=Max('activiteshared__date_last_modif')).order_by(
'-mx',
'-date_last_modif',
'-date_publication',)