Reputation: 770
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
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
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