How to return list of ID-s with Django Rest framework serializer?

Viewed 1809

With this type of serializer, I got as an ID value inside the post object of the id of the user that made the post but I want a list of users that liked the post. Following Django documentation, I think that it should look like this but apparently, something is wrong.

User = get_user_model()

class StudentSerializer(serializers.ModelSerializer):
    class Meta(UserCreateSerializer):
        model = User
        fields = ['id', 'name', 'email' ]


class ProjectSerializer(serializers.ModelSerializer):
    class Meta:
        model = ProjectPost
        fields = ['id',
                ...
                'published',]


class LikeSerializer(serializers.ModelSerializer):
    class Meta:
        model = Like
        fields = ['id']

class PostSerializer(serializers.ModelSerializer):
    student = serializers.SerializerMethodField()
    project = serializers.SerializerMethodField()
    likes = serializers.SerializerMethodField()

    class Meta:
        model = Post
        fields = ['id', 'student', 'project', 'likes']
        
    def get_like(self, obj):
        return LikeSerializer(obj).data
    
    def get_student(self, obj):
        return StudentSerializer(obj.student).data

    def get_project(self, obj):
        return ProjectSerializer(obj.project).data

And here are my Models

User = get_user_model()

class Post(models.Model):
    student = models.ForeignKey(User, on_delete=models.CASCADE, default=None, null=True, blank=True, related_name="student")
    project = models.OneToOneField(ProjectPost, on_delete=models.CASCADE, default=None, null=True, blank=True)
    #bookmark = models.ManyToManyField(User, blank=True, related_name='bookmark')

    def get_student(self):
        return self.student.name


class Like(models.Model):
    user = models.ForeignKey(User,unique=True, on_delete=models.CASCADE, default=None, null=True, blank=True)
    post = models.ForeignKey(Post, on_delete=models.CASCADE, default=None, null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def get_user(self):
        print(self.user.id, 'aaa')
        return self.user.id
3 Answers

You're looking for serializers.PrimaryKeyRelatedField.

As per the docs:

PrimaryKeyRelatedField may be used to represent the target of the relationship using its primary key.

For example, the following serializer:

class AlbumSerializer(serializers.ModelSerializer):
    tracks = serializers.PrimaryKeyRelatedField(many=True, read_only=True)

    class Meta:
        model = Album
        fields = ['album_name', 'artist', 'tracks']

Would serialize to a representation like this:

{
    'album_name': 'Undun',
    'artist': 'The Roots',
    'tracks': [
        89,
        90,
        91,
        ...
    ]
}

To get a list of user IDs that liked a post, in PostSerializer you could use another SerializerMethodField like this:

class PostSerializer(serializers.ModelSerializer):
    users_liked = serializers.SerializerMethodField()
    

def get_users_liked(self, obj):
    return obj.like_set.all().values_list("user__id", flat=True) 

What you are looking for is a reverse relationship. Since you didn't specify a related_name on the Like model, you need to add like_set to your fields list. If you specify a related_name="likes" then you would just have to add likes without the SerializerMethodField. If you are unsure of what attributes you have access to, try importing the Like model into a python manage.py shell and run dir(Like). This should show you all the things.

Related