bayman
bayman

Reputation: 1719

How to retrieve foreign key field in Django rest framework?

Given the model and serializer classes below, when I retrieve Track details, it'll only show the Track title but not the related Artist.

How would I also show the Artist name when retrieving Track details?

models.py

class Artist (models.Model):
    name = models.CharField(max_length=100)

    def __str__(self):
        return self.name

class Track (models.Model):    
    artist = models.ForeignKey(Artist, blank=True, null=True, on_delete=models.SET_NULL, verbose_name="Artist")
    title = models.CharField(max_length=100, verbose_name="Title")

    def __str__(self):
        return self.title

serializers.py

class ArtistSerializer(serializers.ModelSerializer):

    id = serializers.IntegerField(read_only=True)
    name = serializers.CharField()

    class Meta:
        model = Artist
        fields = ('id', 'name')

class TrackSerializer(serializers.ModelSerializer):

    class Meta:
        model = Track
        fields = '__all__'

Upvotes: 13

Views: 14362

Answers (4)

Sergey M.
Sergey M.

Reputation: 298

I think you need custom field, try this serializer:

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

    artist_name = serializers.SerializerMethodField('get_artists_name')

    def get_artists_name(self, obj):
        return obj.artist.name

It produce something like this.

[
    {
        "title": "Don't let me down",
        "artist": 2,
        "artist_name": "The Beatles"
    },
    {
        "title": "Summertime",
        "artist": 1,
        "artist_name": "Ella Fitzgerald"
    }
]

Upvotes: 20

Dr Manhattan
Dr Manhattan

Reputation: 14037

In the current version of DRF you can simply do this

class TrackSerializer(serializers.ModelSerializer):
    
    artist = serializers.StringRelatedField()

    class Meta:
        model = Track
        fields = '__all__'

StringRelatedField may be used to represent the target of the relationship using its __str__ method.

REF

Upvotes: 2

zaidfazil
zaidfazil

Reputation: 9235

Try this serializer,

class ArtistSerializer(serializers.ModelSerializer):

    class Meta:
        model = Artist
        fields = '__all__' # or array of fieldnames like ['name_1', 'name_2']

class TrackSerializer(serializers.ModelSerializer):
    artist = ArtistSerializer()

    class Meta:
        model = Track
        fields = ('title', 'artist')

Inorder to retrieve Artist details, which is a ForeignKey model, you need to use a nested serializer in django-rest-framework.

By using the TrackSerializer with a nested ArtistSerializer, the retrieved data would look something like this,

{
    "title": "Some_Title",
    "artist": {
                   "id": 2, #or id of the artist.
                   "name": "Artist_name"
               }
}

Upvotes: 11

rezkam
rezkam

Reputation: 1357

As you can see in the official django rest framework documentations You should define a serializer field for nested items

First create your Artist (nested item) serializer

class ArtistSerializer(serializers.ModelSerializer):

    id = serializers.IntegerField(read_only=True)
    name = serializers.CharField()

    class Meta:
        model = Artist
        fields = ('id', 'name')

Then you can use it on related model serializers

class TrackSerializer(serializers.ModelSerializer):
    artist = ArtistSerializer()

    class Meta:
        model = Track
        fields = ('title', 'artist')

Upvotes: 4

Related Questions