darkstar
darkstar

Reputation: 1008

How to get value of model method in Django Rest Framework?

So basically I have a django model that has a ManyToManyField of friends and two methods that run on it. Here are my files:

Models.py:

from django.db import models
from django.contrib.auth.models import User


class Profile(models.Model):
    first_name = models.CharField(max_length=50, blank=True)
    last_name = models.CharField(max_length=50, blank=True)
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    friends = models.ManyToManyField(User, blank=True, related_name='friends')

    def friends_list(self):
        return self.friends.all()

    def number_of_friends(self):
        return self.friends.all().count()

Serialzers.py:

from rest_framework import serializers
from .models import Profile


class ProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = Profile
        fields = '__all__'

Views.py:

from rest_framework import viewsets, permissions
from .models import Profile
from .serializers import ProfileSerializer


class ProfileViewSet(viewsets.ModelViewSet):
    queryset = Profile.objects.all()
    permission_classes = [
        permissions.AllowAny
    ]
    serializer_class = ProfileSerializer

The issue is that in the Api, the return values of the method aren't there. The friends_list method for example is supposed to return a list of friends you have and even though this does work in a traditional django project, the Django Rest Framework is not showing any value for this method. How can I fix this and get the return values for both methods to show up in the api?

Upvotes: 2

Views: 2649

Answers (2)

urek mazino
urek mazino

Reputation: 165

when you use __all__ it call fields only you have to call fields with methods using list like that

`fileds = ["first_name","last_name","user",
           "friends","friends_list","number_of_friends"
           ]`

Upvotes: 1

Resley Rodrigues
Resley Rodrigues

Reputation: 2288

Since the model serializer picks up only model fields for the serializer fields, you won't automatically get any methods copied over.

You can still send this read only data over the API by explicitly adding the two fields with reference to the model methods

class ProfileSerializer(serializers.ModelSerializer):
    class Meta:
        model = Profile
        fields = [
            # need to explicitly define all fields I believe
            'friends_list',
            'number_of_friends',
        ]

Now that the two fields (matching the method name are declared, DRF should create SerializerMethodField or ReadOnly field (not sure which one, but they are similar) for each of them. It works coz it sets the source for those fields to be the same name, and if finds some attribute (in this case the methods) on the model.

If that doesn't work, you can

class ProfileSerializer(serializers.ModelSerializer):
    friends_list = serializers.SerializerMethodField()
    number_of_friends = serializers.SerializerMethodField()

    class Meta:
        model = Profile
        fields = [
            # need to explicitly define all fields I believe
            'friends_list',
            'number_of_friends',
        ]

    def get_friends_list(self, instance):
        return instance.friends_list()

    def get_number_of_friends(self, instance):
        return instance.number_of_friends()

Upvotes: 6

Related Questions