From 08b28a7d9864f6fec0f01df4c33b772f42cfb9aa Mon Sep 17 00:00:00 2001 From: Eliot Berriot Date: Mon, 19 Mar 2018 19:07:45 +0100 Subject: [PATCH] Added playlist tracks count and modification date in API --- .../migrations/0004_auto_20180319_1642.py | 23 +++++++++++++++++++ api/funkwhale_api/playlists/models.py | 5 ++++ api/funkwhale_api/playlists/serializers.py | 21 +++++++++++++++-- api/funkwhale_api/playlists/views.py | 9 +++++++- api/tests/playlists/test_models.py | 2 ++ api/tests/playlists/test_views.py | 10 ++++++++ 6 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 api/funkwhale_api/playlists/migrations/0004_auto_20180319_1642.py diff --git a/api/funkwhale_api/playlists/migrations/0004_auto_20180319_1642.py b/api/funkwhale_api/playlists/migrations/0004_auto_20180319_1642.py new file mode 100644 index 000000000..f4a525291 --- /dev/null +++ b/api/funkwhale_api/playlists/migrations/0004_auto_20180319_1642.py @@ -0,0 +1,23 @@ +# Generated by Django 2.0.3 on 2018-03-19 16:42 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('playlists', '0003_auto_20180319_1214'), + ] + + operations = [ + migrations.AddField( + model_name='playlist', + name='modification_date', + field=models.DateTimeField(auto_now=True), + ), + migrations.AlterField( + model_name='playlisttrack', + name='index', + field=models.PositiveIntegerField(blank=True, null=True), + ), + ] diff --git a/api/funkwhale_api/playlists/models.py b/api/funkwhale_api/playlists/models.py index d8c90aef9..f26dbeff4 100644 --- a/api/funkwhale_api/playlists/models.py +++ b/api/funkwhale_api/playlists/models.py @@ -11,6 +11,8 @@ class Playlist(models.Model): user = models.ForeignKey( 'users.User', related_name="playlists", on_delete=models.CASCADE) creation_date = models.DateTimeField(default=timezone.now) + modification_date = models.DateTimeField( + auto_now=True) privacy_level = fields.get_privacy_field() def __str__(self): @@ -65,10 +67,13 @@ class Playlist(models.Model): plt.index = index plt.save(update_fields=['index']) + self.save(update_fields=['modification_date']) return index + @transaction.atomic def remove(self, index): existing = self.playlist_tracks.select_for_update() + self.save(update_fields=['modification_date']) to_update = existing.filter(index__gt=index) return to_update.update(index=models.F('index') - 1) diff --git a/api/funkwhale_api/playlists/serializers.py b/api/funkwhale_api/playlists/serializers.py index 43e2414d4..0680dc8d0 100644 --- a/api/funkwhale_api/playlists/serializers.py +++ b/api/funkwhale_api/playlists/serializers.py @@ -62,8 +62,25 @@ class PlaylistTrackWriteSerializer(serializers.ModelSerializer): class PlaylistSerializer(serializers.ModelSerializer): + tracks_count = serializers.SerializerMethodField() class Meta: model = models.Playlist - fields = ('id', 'name', 'privacy_level', 'creation_date') - read_only_fields = ['id', 'creation_date'] + fields = ( + 'id', + 'name', + 'tracks_count', + 'privacy_level', + 'creation_date', + 'modification_date') + read_only_fields = [ + 'id', + 'modification_date', + 'creation_date',] + + def get_tracks_count(self, obj): + try: + return obj.tracks_count + except AttributeError: + # no annotation? + return obj.playlist_tracks.count() diff --git a/api/funkwhale_api/playlists/views.py b/api/funkwhale_api/playlists/views.py index 02e53cb16..dc3475fab 100644 --- a/api/funkwhale_api/playlists/views.py +++ b/api/funkwhale_api/playlists/views.py @@ -1,3 +1,5 @@ +from django.db.models import Count + from rest_framework import generics, mixins, viewsets from rest_framework import status from rest_framework.decorators import detail_route @@ -8,6 +10,7 @@ from funkwhale_api.music.models import Track from funkwhale_api.common import permissions from funkwhale_api.common import fields +from . import filters from . import models from . import serializers @@ -21,13 +24,17 @@ class PlaylistViewSet( viewsets.GenericViewSet): serializer_class = serializers.PlaylistSerializer - queryset = (models.Playlist.objects.all()) + queryset = ( + models.Playlist.objects.all() + .annotate(tracks_count=Count('playlist_tracks')) + ) permission_classes = [ permissions.ConditionalAuthentication, permissions.OwnerPermission, IsAuthenticatedOrReadOnly, ] owner_checks = ['write'] + filter_class = filters.PlaylistFilter @detail_route(methods=['get']) def tracks(self, request, *args, **kwargs): diff --git a/api/tests/playlists/test_models.py b/api/tests/playlists/test_models.py index dfe40187d..da3e23e28 100644 --- a/api/tests/playlists/test_models.py +++ b/api/tests/playlists/test_models.py @@ -5,6 +5,7 @@ from django import forms def test_can_insert_plt(factories): plt = factories['playlists.PlaylistTrack']() + modification_date = plt.playlist.modification_date assert plt.index is None @@ -12,6 +13,7 @@ def test_can_insert_plt(factories): plt.refresh_from_db() assert plt.index == 0 + assert plt.playlist.modification_date > modification_date def test_insert_use_last_idx_by_default(factories): diff --git a/api/tests/playlists/test_views.py b/api/tests/playlists/test_views.py index 192aad382..03babfabb 100644 --- a/api/tests/playlists/test_views.py +++ b/api/tests/playlists/test_views.py @@ -23,6 +23,16 @@ def test_can_create_playlist_via_api(logged_in_api_client): assert playlist.privacy_level == 'everyone' +def test_serializer_includes_tracks_count(factories, logged_in_api_client): + playlist = factories['playlists.Playlist']() + plt = factories['playlists.PlaylistTrack'](playlist=playlist) + + url = reverse('api:v1:playlists-detail', kwargs={'pk': playlist.pk}) + response = logged_in_api_client.get(url) + + assert response.data['tracks_count'] == 1 + + def test_playlist_inherits_user_privacy(logged_in_api_client): url = reverse('api:v1:playlists-list') user = logged_in_api_client.user