Opeyemi Odedeyi
Opeyemi Odedeyi

Reputation: 770

how to get Json response formatted differently on django

I have a custom user model and i implemented a user following and follower system that works well. But the problem I have is that when I request for the followers a particular user has, the JSON response I get is not exactly the way I want it returned. more details below

models

class User(AbstractBaseUser, PermissionsMixin):
    username = None
    email = models.EmailField(max_length=254, unique=True)
    name = models.CharField(max_length=250)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    last_login = models.DateTimeField(null=True, blank=True)
    date_joined = models.DateTimeField(auto_now_add=True)
    slug = models.SlugField(max_length=255, unique=True, blank=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['name']

class FollowLog(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='followers')
    followed_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE,
                                    related_name='following', null=True)
    followed_on = models.DateTimeField(auto_now_add=True)
    status = models.CharField(choices=FOLLOW_STATUS, default=FollowStatus.following.value, max_length=30)
    updated_on = models.DateTimeField(auto_now=True)
    unfollowed_on = models.DateTimeField(null=True)
    blocked_on = models.DateTimeField(null=True)

serializer

class FollowerSerializer(serializers.ModelSerializer):
    '''
    Allows people to view follower of a user
    '''
    followed_by = serializers.SlugRelatedField(read_only=True, slug_field='slug')

    class Meta:
        model = FollowLog
        fields = ('followed_by',)
        read_only_fields = ('followed_by',)

view

class UserFollowerView(APIView):
    '''
    Gets all the followers to a user
    '''
    permission_classes = [AllowAny]

    def get(self, request, slug):
        user = User.objects.get(slug=slug)
        followers = user.followers.all().filter(status='following').order_by("-followed_on")
        serializer = FollowerSerializer(followers, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

when I run the above, I get the appropriate response but in this format

JSON response I get

[
    {
        "followed_by": "opeyemi-odedeyi-qqmunu13o4b8vd4"
    },
    {
        "followed_by": "modupeoluwa-odedeyi-m7ji5qj5szu2uqo"
    }
]

I would prefer it if I got a response like below

preferred response I want to get

{
    "followed_by": [
        "opeyemi-odedeyi-qqmunu13o4b8vd4",
        "modupeoluwa-odedeyi-m7ji5qj5szu2uqo"
    ]
}

Upvotes: 0

Views: 52

Answers (2)

Sarthak Kumar
Sarthak Kumar

Reputation: 81

You can make a custom renderer for your api and change the format of the response however so you want.

class UserFollowerView(APIView):
    '''
    Gets all the followers to a user
    '''
    permission_classes = [AllowAny]
    renderer_classes = (UserFollowerRenderer, )

    def get(self, request, slug):
        user = User.objects.get(slug=slug)
        followers = user.followers.all().filter(status='following').order_by("-followed_on")
        serializer = FollowerSerializer(followers, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

and the renderer can be something like this :-

class UserFollowerRenderer(CoreJSONRenderer):
    charset = "utf-8"

    def render(self, data, media_type=None, renderer_context=None):
        if not data:
            return "[]"
        final_data = list()
        for element in data:
            final_data.append(element.get('followed_by'))
        result = dict(followed_by=final_data)
        return json_dumps(result)

Upvotes: 1

HuLu ViCa
HuLu ViCa

Reputation: 5452

A serializer will always return a dictionary, and if you set many=true, it will return an array of dictionaries.

What you can do is to get the array you want from the array of dictionaries returned by the serializer:

class UserFollowerView(APIView):
    '''
    Gets all the followers to a user
    '''
    permission_classes = [AllowAny]

    def get(self, request, slug):
        user = User.objects.get(slug=slug)
        followers = user.followers.all().filter(status='following').order_by("-followed_on")
        data = FollowerSerializer(followers, many=True).data
        data_to_return = list(map(lambda item: item['followed_by'], data))
        return Response(data_to_return, status=status.HTTP_200_OK)

Upvotes: 2

Related Questions