Django How to Serialize from ManyToManyField and List All
Solution 1
I think what you need is the nested serializer:
class FollowerSerializer(serializers.ModelSerializer):
username = serializers.CharField(source='user__username')
class Meta:
model = UserProfile
fields = ('username', )
class FollowerSerializer(serializers.ModelSerializer):
followers = FollowerSerializer(many=True, read_only=True)
class Meta:
model = UserProfile
fields = ('followers', )
Solution 2
I used nested relationships in this link. Django Rest Framework Nested Relationships
Added a new serializer for only username of the user and also changed the other serializer.
# serializes only usernames of users
class EachUserSerializer(serializers.ModelSerializer):
username = serializers.CharField(source='user.username')
class Meta:
model = UserProfile
fields = ('username',)
class FollowerSerializer(serializers.ModelSerializer):
followers = EachUserSerializer(many=True, read_only= True)
followings = EachUserSerializer(many=True,read_only=True)
class Meta:
model = UserProfile
fields = ('followers','followings')
Output was just what was I looking for:
{
"followers": [],
"followings": [
{
"username": "sneijder"
},
{
"username": "drogba"
}
]
}
Thank you for your help anyway :)
Cagatay Barin
Updated on June 04, 2022Comments
-
Cagatay Barin almost 2 years
I'm developing a mobile application backend with Django 1.9.1 I implemented the follower model and now I want to list all of the followers of a user but I'm currently stuck to do that. I also use Django Rest Framework.
This is my UserProfile model
class UserProfile(models.Model): # Linking UserProfile to User model. user = models.OneToOneField(User) city = models.CharField(null=True, max_length=30, blank=True) gender = models.CharField(null=True, max_length=10, blank=True) # m for male, f for female # TODO: Fix the picture later. # picture = models.ImageField(upload_to='profile_images', blank=True) age = models.IntegerField(null=True, blank=True) caption = models.CharField(null=True, max_length=40, blank=True) following_count = models.IntegerField(default=0) follower_count = models.IntegerField(default=0) post_count = models.IntegerField(default=0) like_count = models.IntegerField(default=0) date = models.DateTimeField(default=datetime.now(), blank=True) is_protected = models.BooleanField(default=False) is_facebook_created_user = models.BooleanField(default=False) facebook_id = models.CharField(default='', blank=True, max_length=350) picture_url = models.URLField(blank=True, max_length=100, null=True) followings = models.ManyToManyField('self', related_name='following', symmetrical=False) followers = models.ManyToManyField('self', related_name='follower', symmetrical=False) blocking = models.ManyToManyField('self', related_name='block', symmetrical=False) blocked_by = models.ManyToManyField('self', related_name='blocked', symmetrical=False) def block_user(self,username): other = UserProfile.objects.get(user__username=username) if not self.is_blocking(username): self.blocking.add(other) other.blocked_by.add(self) return True else: return False def unblock_user(self, username): other = UserProfile.objects.get(user__username=username) if self.is_blocking(username): self.blocking.remove(other) other.blocked_by.remove(self) return True else: return False def follow_user(self, username): other = UserProfile.objects.get(user__username=username) if not self.is_following(username): self.followings.add(other) self.following_count = self.followings.all().count() self.save() other.followers.add(self) other.follower_count = other.followers.all().count() other.save() return True else: return False def unfollow_user(self, username): other = UserProfile.objects.get(user__username=username) if self.is_following(username): self.followings.remove(other) self.following_count = self.followings.all().count() self.save() other.followers.remove(self) other.follower_count = other.followers.all().count() other.save() return True else: return False def is_blocking(self,username): return self.blockings.all().filter(user__username=username).exists() def is_blocked_by(self,username): return self.blocked_by.all().filter(user__username=username).exists() def is_following(self, username): #returns Bool return self.followings.all().filter(user__username=username).exists() def is_followed_by(self, username): #returns Bool return self.followers.all().filter(user__username=username).exists() def __unicode__(self): return self.user.username def get_token(self): try: token = Token.objects.get(user_id=self.user_id) except: token = 'error' return token def get_username(self): return self.user.username
As you see, I user ManyToManyField for followers. Now I want to list followers of a user but I don't want to list just all of their information since it's unnecessary. I just want to list their usernames because no need for whole information and it's just a waste.
Here is my followers view.
@api_view(['GET']) def get_followers(request): username = request.query_params.get('username', None) if username is not None: if UserProfile.objects.all().filter(user__username=username).exists(): wanted = UserProfile.objects.get(user__username=username) followers = wanted.followers.all() serializer = FollowerSerializer(followers) return JsonResponse(serializer.data) else: return JsonResponse({"result": "user_does_not_exist"}) else: #TODO: return current user's followers return JsonResponse({"result": "provide_username"})
Also I added a serializer for only followers of user.
class FollowerSerializer(serializers.ModelSerializer): class Meta: model = UserProfile field = ('followers',)
The problem is, it just lists the all of the user information and it doesn't give usernames but it only lists their id's which i can't do anything.
I forgot to mention that I did think of using ListAPIView but I can't get the username parameter with that. If there is a way of getting the parameter, I could also use ListAPIView for followers.
How can I fix this problem and list only their usernames? Any help will be appreciated.