[Django]-Retrieving a Foreign Key value with django-rest-framework serializers

121πŸ‘

βœ…

Just use a related field without setting many=True.

Note that also because you want the output named category_name, but the actual field is category, you need to use the source argument on the serializer field.

The following should give you the output you need…

class ItemSerializer(serializers.ModelSerializer):
    category_name = serializers.RelatedField(source='category', read_only=True)

    class Meta:
        model = Item
        fields = ('id', 'name', 'category_name')
πŸ‘€Tom Christie

176πŸ‘

In the DRF version 3.6.3 this worked for me

class ItemSerializer(serializers.ModelSerializer):
    category_name = serializers.CharField(source='category.name')

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

More info can be found here: Serializer Fields core arguments

πŸ‘€Sayok88

42πŸ‘

Another thing you can do is to:

  • create a property in your Item model that returns the category name and
  • expose it as a ReadOnlyField.

Your model would look like this.

class Item(models.Model):
    name = models.CharField(max_length=100)
    category = models.ForeignKey(Category, related_name='items')

    def __unicode__(self):
        return self.name

    @property
    def category_name(self):
        return self.category.name

Your serializer would look like this. Note that the serializer will automatically get the value of the category_name model property by naming the field with the same name.

class ItemSerializer(serializers.ModelSerializer):
    category_name = serializers.ReadOnlyField()

    class Meta:
        model = Item
πŸ‘€hsebastian

30πŸ‘

this worked fine for me:

class ItemSerializer(serializers.ModelSerializer):
    category_name = serializers.ReadOnlyField(source='category.name')
    class Meta:
        model = Item
        fields = "__all__"
πŸ‘€suhailvs

18πŸ‘

Simple solution
source='category.name' where category is foreign key and .name it’s attribute.

from rest_framework.serializers import ModelSerializer, ReadOnlyField
from my_app.models import Item

class ItemSerializer(ModelSerializer):
    category_name = ReadOnlyField(source='category.name')

    class Meta:
        model = Item
        fields = "__all__"
πŸ‘€Anurag Misra

12πŸ‘

Worked on 08/08/2018 and on DRF version 3.8.2:

class ItemSerializer(serializers.ModelSerializer):
    category_name = serializers.ReadOnlyField(source='category.name')

    class Meta:
        model = Item
        read_only_fields = ('id', 'category_name')
        fields = ('id', 'category_name', 'name',)

Using the Meta read_only_fields we can declare exactly which fields should be read_only. Then we need to declare the foreign field on the Meta fields (better be explicit as the mantra goes: zen of python).

πŸ‘€John Moutafis

5πŸ‘

This solution is better because of no need to define the source model. But the name of the serializer field should be the same as the foreign key field name

class ItemSerializer(serializers.ModelSerializer):
    category = serializers.SlugRelatedField(read_only=True, slug_field='title')

    class Meta:
        model = Item
        fields = ('id', 'name', 'category')
πŸ‘€zshanabek

0πŸ‘

For those that want to replace the field of the ForeignKey (that displays the ID) you can still used the __all__ syntax for convenience and simply over-write the field name as you see fit. For example:

class MyModelSerializer(serializers.ModelSerializer):

    # override the category field that would otherwise show an integer value 
    # for the ID with the field of that model you choose. "name" here.
    category = serializers.ReadOnlyField(source='category.name')

    class Meta:
        model = MyModel
        fields = '__all__'

IMO this is convenient b/c you can still use the __all__ syntax to capture any added fields later. Anything that’s getting overridden is manually done so and, if needing to be reverted, can be manually done some without changing any other syntax.

πŸ‘€alphazwest

Leave a comment