Skip to content
Snippets Groups Projects
serializers.py 4.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • from django.db import transaction
    
    from funkwhale_api.common import preferences
    
    from funkwhale_api.music.models import Track
    
    from funkwhale_api.music.serializers import TrackSerializer
    
    from funkwhale_api.users.serializers import UserBasicSerializer
    
    from . import models
    
    
    class PlaylistTrackSerializer(serializers.ModelSerializer):
    
        # track = TrackSerializer()
        track = serializers.SerializerMethodField()
    
            fields = ("id", "track", "playlist", "index", "creation_date")
    
        def get_track(self, o):
            track = o._prefetched_track if hasattr(o, "_prefetched_track") else o.track
            return TrackSerializer(track).data
    
    class PlaylistTrackWriteSerializer(serializers.ModelSerializer):
    
    Eliot Berriot's avatar
    Eliot Berriot committed
        index = serializers.IntegerField(required=False, min_value=0, allow_null=True)
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            fields = ("id", "track", "playlist", "index")
    
        def validate_playlist(self, value):
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            if self.context.get("request"):
    
                # validate proper ownership on the playlist
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                if self.context["request"].user != value.user:
    
                    raise serializers.ValidationError(
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                        "You do not have the permission to edit this playlist"
                    )
    
            existing = value.playlist_tracks.count()
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            max_tracks = preferences.get("playlists__max_tracks")
    
                raise serializers.ValidationError(
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                    "Playlist has reached the maximum of {} tracks".format(max_tracks)
                )
    
        @transaction.atomic
        def create(self, validated_data):
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            index = validated_data.pop("index", None)
    
            instance = super().create(validated_data)
            instance.playlist.insert(instance, index)
            return instance
    
        @transaction.atomic
        def update(self, instance, validated_data):
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            update_index = "index" in validated_data
            index = validated_data.pop("index", None)
    
            super().update(instance, validated_data)
            if update_index:
                instance.playlist.insert(instance, index)
            return instance
    
        def get_unique_together_validators(self):
            """
            We explicitely disable unique together validation here
            because it collides with our internal logic
            """
            return []
    
    
    
    class PlaylistSerializer(serializers.ModelSerializer):
    
        tracks_count = serializers.SerializerMethodField(read_only=True)
    
        duration = serializers.SerializerMethodField(read_only=True)
        album_covers = serializers.SerializerMethodField(read_only=True)
    
        user = UserBasicSerializer(read_only=True)
    
        is_playable = serializers.SerializerMethodField()
    
    Eliot Berriot's avatar
    Eliot Berriot committed
                "id",
                "name",
                "user",
                "modification_date",
                "creation_date",
                "privacy_level",
    
                "tracks_count",
                "album_covers",
                "duration",
    
                "is_playable",
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            )
            read_only_fields = ["id", "modification_date", "creation_date"]
    
        def get_is_playable(self, obj):
            try:
    
                return bool(obj.playable_plts)
    
            except AttributeError:
                return None
    
    
        def get_tracks_count(self, obj):
            try:
                return obj.tracks_count
            except AttributeError:
                # no annotation?
                return obj.playlist_tracks.count()
    
        def get_duration(self, obj):
            try:
                return obj.duration
            except AttributeError:
                # no annotation?
                return 0
    
        def get_album_covers(self, obj):
            try:
                plts = obj.plts_for_cover
            except AttributeError:
                return []
    
    
            excluded_artists = []
    
            try:
                user = self.context["request"].user
            except (KeyError, AttributeError):
                user = None
            if user and user.is_authenticated:
                excluded_artists = list(
                    user.content_filters.values_list("target_artist", flat=True)
                )
    
    
            covers = []
            max_covers = 5
            for plt in plts:
    
                if plt.track.album.artist_id in excluded_artists:
                    continue
    
                url = plt.track.album.cover.crop["200x200"].url
    
                if url in covers:
                    continue
                covers.append(url)
                if len(covers) >= max_covers:
                    break
    
            full_urls = []
            for url in covers:
                if "request" in self.context:
                    url = self.context["request"].build_absolute_uri(url)
                full_urls.append(url)
            return full_urls
    
    
    
    class PlaylistAddManySerializer(serializers.Serializer):
        tracks = serializers.PrimaryKeyRelatedField(
    
    Eliot Berriot's avatar
    Eliot Berriot committed
            many=True, queryset=Track.objects.for_nested_serialization()
        )