0
votes

I am using Django DRF, and having difficulty in applying SerializerMethodField (https://www.django-rest-framework.org/api-guide/fields/#serializermethodfield)

Following is a simple case of typical model, serializer code, which works perfectly.

serializer.py (before)

from django.contrib.auth.models import User
from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = '__all__'

view.py (before)

@api_view(['GET'])
def GetAllUsers(request):
    Users = User.objects.all()
    serializer = UserSerializer(Users, many=True)
    return Response(serializer.data)

In order to deliver additional information which is not included in the model, I changed serializer

serializer.py (after)

from django.contrib.auth.models import User
from django.utils.timezone import now
from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    days_since_joined = serializers.SerializerMethodField()

    class Meta:
        model = User

    def get_days_since_joined(self, obj):
        return (now() - obj.date_joined).days

Now I have to find a way to give obj(which has date_joined inside) to serializer, and I think I have to do it in view.py

But I don't know how to do it.

Thanks

2
obj is the instance of the model and it is passed by the serializer to the method. What do you want to do exactly? Is the obj you speak of not the User instance whose date_joined you want to use? - Abdul Aziz Barkat
To me this seems valid, could you include a traceback or description of what is not going as expected? - David Louda
@AbdulAzizBarkat My understanding is that obj is not the instance of the model. It is simply a variable given to the serializer. Here I don't know how to use get_days_since_joined(obj) and UserSerializer from view.py - Jeehoon Park
@DavidLouda Sorry there is no traceback. Because I don't know how to write view.py file to call get_days_since_joined. - Jeehoon Park
@JeehoonPark did you try running this. It would work properly, if there is something else you are trying and want to do you should add that to your question. (Note: you don't need to call get_days_since_joined that would be done by the serializer) - Abdul Aziz Barkat

2 Answers

1
votes

You can pass extra context to serializer like this

view.py

@api_view(['GET'])
def GetAllUsers(request):
    Users = User.objects.all()
    context = {"extra_obj": extra_obj}
    serializer = UserSerializer(Users, many=True, context=context)
    return Response(serializer.data)

serializer.py

from django.contrib.auth.models import User
from django.utils.timezone import now
from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    days_since_joined = serializers.SerializerMethodField()

    class Meta:
        model = User

    def get_days_since_joined(self, obj):
        extra_obj = self.context.get("extra_obj")
        return (now() - extra_obj.date_joined).days

reference the official document here

0
votes

You just have to include SerializerMethodField name and other model fields which you want to return to api.

There is no need to change views.py, you just have to change serializer.py.

In your case serializer.py will be like

from django.contrib.auth.models import User
from django.utils.timezone import now
from rest_framework import serializers

class UserSerializer(serializers.ModelSerializer):
    days_since_joined = serializers.SerializerMethodField()

    class Meta:
        model = User
        fields = [
            'id',
            'name',
            'days_since_joined',
        ]


    def get_days_since_joined(self, obj):
        return (now() - obj.date_joined).days