ArchitW
ArchitW

Reputation: 25

Get Value of Foreign Key in Django-rest Serializer

I am trying to get value of foreign key , but i am only getting id, my code below

Model:
    class DocumentType(models.Model):
    """Model for type of documents type system is indexing"""
    title = models.CharField(max_length=255, null=False)

def __str__(self):
    return "{}".format(self.title)


class DocumentsCount(models.Model):
    """Model for type of documents count system is indexing"""
    document_type = models.ForeignKey(DocumentType, on_delete=models.CASCADE, related_name='doc_title')
    count = models.IntegerField(default=0)

    def __str__(self):
        return "{}".format(self.document_type)

Serializer

class DocumentCountsSerializer(serializers.ModelSerializer):
title = serializers.ReadOnlyField(source="DocumentType.title")

class Meta:
    model = DocumentsCount
    fields = "__all__"

Out put I am getting from API

    {
    "id": 5,
    "count": 2,
    "document_type": 3
}

document_type should be title , but i am getting ID

this is query

 queryset = DocumentsCount.objects.select_related('document_type')

I am not sure what did I did wrong, I am in fact getting ID and Title when u print queryset and run in sqlite

Upvotes: 1

Views: 7788

Answers (4)

Amrit
Amrit

Reputation: 11

The easiest way is to use StringRelatedField property/attribute of rest framework while making serializers. It gives output as per the definition in __str__(self) of the model.

See an example (if one to Many: you can use many=True):

Your snippet will go like this:

class DocumentCountsSerializer(serializers.ModelSerializer):
    document_type = serializers.StringRelatedField()

    class Meta:
        model = DocumentsCount
        fields = "__all__"

To add on (an additional info), if the serializer was of your class DocumentType , then we have to use: many=True, example is in subsequent field:

class DocumentTypeSerializer(serializers.ModelSerializer):
    # here we use related_name 'doc_title' for the relationship
    doc_title = serializers.StringRelatedField(many=True)

    class Meta:
        model = DocumentsType
        fields = "__all__"

Upvotes: 1

slider
slider

Reputation: 12990

You have a mistake in specifying the source. Change it to source="document_type.title" because you want to say "use the title of the document_type field of this instance":

class DocumentCountsSerializer(serializers.ModelSerializer):
    title = serializers.CharField(source="document_type.title", read_only=True)

    class Meta:
        model = DocumentsCount
        fields = "__all__"

You were having a problem because there's no field DocumentType defined on the DocumentsCount model (the field is document_type which is a foreign key to DocumentType).

Upvotes: 4

Haren Lewis
Haren Lewis

Reputation: 161

The answer posted by a_k_v is correct and will return a nested serializer within the DocumentCountsSerializer().

Alternatively if you want a response like this with:

{ "id": 5, "count": 2, "title": "title here" }

You need to update your serializer accordingly. Considering the query your run with select_related, your serializers will look something like this:

class DocumentCountsSerializer(serializers.ModelSerializer):
    title = serializers.SerializerMethodField()

    class Meta:
        model = DocumentsCount
        fields = "__all__"

     def get_title(self, obj):
         return obj.document_type.title

Upvotes: 0

a_k_v
a_k_v

Reputation: 1608

Update your model to support nested serializer like this

class DocumentTypeSerializer(serializers.ModelSerializer):
       class Meta:
            model = DocumentType
            fields = "__all__"
class DocumentCountsSerializer(serializers.ModelSerializer):
    doc_title = DocumentTypeSerializer(many=True)

    class Meta:
        model = DocumentsCount
        fields = "__all__"

By calling the DocumentCountsSerializer for fetching data automatically fetch related foreign key values.

Call the serializer as follows:

queryset = DocumentsCount.objects.all()
serializer = serializers.DocumentTypeSerializer(queryset, many=True)

Upvotes: 0

Related Questions