From 16f631af1a379e6e52888278d433611e5f9e1e3d Mon Sep 17 00:00:00 2001
From: Eliot Berriot <contact@eliotberriot.com>
Date: Tue, 20 Mar 2018 22:44:28 +0100
Subject: [PATCH] Performance optimization on playlisttrack serialization

---
 api/funkwhale_api/playlists/models.py | 11 +++++++++++
 api/funkwhale_api/playlists/views.py  |  7 +++++--
 2 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/api/funkwhale_api/playlists/models.py b/api/funkwhale_api/playlists/models.py
index ed4307b675..6bb8fe1782 100644
--- a/api/funkwhale_api/playlists/models.py
+++ b/api/funkwhale_api/playlists/models.py
@@ -94,6 +94,15 @@ class Playlist(models.Model):
         ]
         return PlaylistTrack.objects.bulk_create(plts)
 
+class PlaylistTrackQuerySet(models.QuerySet):
+    def for_nested_serialization(self):
+        return (self.select_related()
+                    .select_related('track__album__artist')
+                    .prefetch_related(
+                        'track__tags',
+                        'track__files',
+                        'track__artist__albums__tracks__tags'))
+
 
 class PlaylistTrack(models.Model):
     track = models.ForeignKey(
@@ -105,6 +114,8 @@ class PlaylistTrack(models.Model):
         Playlist, related_name='playlist_tracks', on_delete=models.CASCADE)
     creation_date = models.DateTimeField(default=timezone.now)
 
+    objects = PlaylistTrackQuerySet.as_manager()
+
     class Meta:
         ordering = ('-playlist', 'index')
         unique_together = ('playlist', 'index')
diff --git a/api/funkwhale_api/playlists/views.py b/api/funkwhale_api/playlists/views.py
index a077dec27d..5de6067ffe 100644
--- a/api/funkwhale_api/playlists/views.py
+++ b/api/funkwhale_api/playlists/views.py
@@ -46,7 +46,7 @@ class PlaylistViewSet(
     @detail_route(methods=['get'])
     def tracks(self, request, *args, **kwargs):
         playlist = self.get_object()
-        plts = playlist.playlist_tracks.all()
+        plts = playlist.playlist_tracks.all().for_nested_serialization()
         serializer = serializers.PlaylistTrackSerializer(plts, many=True)
         data = {
             'count': len(plts),
@@ -65,6 +65,9 @@ class PlaylistViewSet(
         except exceptions.ValidationError as e:
             payload = {'playlist': e.detail}
             return Response(payload, status=400)
+        ids = [p.id for p in plts]
+        plts = models.PlaylistTrack.objects.filter(
+            pk__in=ids).order_by('index').for_nested_serialization()
         serializer = serializers.PlaylistTrackSerializer(plts, many=True)
         data = {
             'count': len(plts),
@@ -93,7 +96,7 @@ class PlaylistTrackViewSet(
         viewsets.GenericViewSet):
 
     serializer_class = serializers.PlaylistTrackSerializer
-    queryset = (models.PlaylistTrack.objects.all())
+    queryset = (models.PlaylistTrack.objects.all().for_nested_serialization())
     permission_classes = [
         permissions.ConditionalAuthentication,
         permissions.OwnerPermission,
-- 
GitLab