Alan
Alan

Reputation: 313

Django Rest Framework Serializer Relations: How to get a list of only the latest track?

I'm following this documentation here. I'm trying to wrap my head around being able to query the Album object and have it only return the latest track versus returning all the tracks. Below is a modified version of the documentation models and serializers.

Models

class AlbumOwner(models.Model):
    username = models.CharField(max_length=100)

class Album(models.Model):
    album_name = models.CharField(max_length=100)
    owner = models.ForeignKey(AlbumOwner, related_name='owner', on_delete=models.CASCADE)

class Track(models.Model):
    album = models.ForeignKey(Album, related_name='tracks', on_delete=models.CASCADE)
    title = models.CharField(max_length=100)
    created_at = models.DateTimeField(auto_now_add=True)   

    class Meta:
        get_latest_by = 'created_at'

Serializers

class TrackSerializer(serializers.ModelSerializer):
    class Meta:
        model = Track
        fields = ('title', 'created_at')

class AlbumSerializer(serializers.ModelSerializer):
    tracks = TrackSerializer(many=True, read_only=True)

    class Meta:
        model = Album
        fields = ('album_name', 'tracks')

The query I am currently using is below, "o" represents the owner:

albums = Album.objects.filter(owner=o)
serializer = AlbumSerializer(albums)
serializer.data

Serializer.data will return a response similar to this:

[{
    'album_name': 'The Grey Album',
    'tracks': [
        {'title': 'Public Service Announcement', "created_at": "2018-06-15T06:22:35.680291Z"},
        {'title': 'What More Can I Say', "created_at": "2014-07-15T06:22:35.680291Z"},
        {'title': 'Encore', "created_at": "2016-07-15T06:22:35.680291Z"}
    ],
},{
    'album_name': 'The Blue Album',
    'tracks': [
        {'title': 'PSA', "created_at": "2002-07-15T06:22:35.680291Z"},
        {'title': 'WMCIS', '"created_at": "2003-07-15T06:22:35.680291Z"},
        {'title': 'E', "created_at": "2005-07-15T06:22:35.680291Z"}
    ],
},
]

The response I want is where only tracks of the latest date are returned:

[{
        'album_name': 'The Grey Album',
        'tracks': [
            {'title': 'Public Service Announcement', "created_at": "2018-06-15T06:22:35.680291Z"}
        ],
    },{
        'album_name': 'The Blue Album',
        'tracks': [
            {'title': 'E', "created_at": "2005-07-15T06:22:35.680291Z"}
        ],
    },
    ]

Upvotes: 2

Views: 2992

Answers (1)

Dušan Maďar
Dušan Maďar

Reputation: 9909

Try something like below, i.e. slice the tracks queryset or select the latest one based on some filter.

class AlbumSerializer(serializers.ModelSerializer):
    tracks = serializers.SerializerMethodField()

    class Meta:
        model = Album
        fields = ('album_name', 'tracks')

    def get_tracks(self, album):
        qs = album.tracks.all()[-1:]
        return TrackSerializer(qs, many=True, read_only=True).data

Upvotes: 7

Related Questions