'DRF add computed field based on requesting user

I have a model which has specific many to many fields to the user model. Now, to prevent information leaking, I do not want to return the whole related field though the rest framework. But, I want to create some kind of computed field, such that it return True if the requesting user is in the related field, and False otherwise. Is there a way to make this work?

For example, as it stands now, the rest framework will list the users for "user_like" and "user_bookmark", which I dont want to happen, hence I want to exclude them from the serialized. But I want to have a field, say, named is_liked, which will be true if request.user is in user_like, and false otherwise.

My current setup:

model

class Post(models.Model):
    title = models.CharField(max_length=100)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    image = models.ImageField(upload_to='dream_photos')

    description = models.TextField(max_length=500)
    date_added = models.DateTimeField(auto_now_add=True)

    user_like = models.ManyToManyField(User, related_name='likes', blank=True)
    user_bookmark = models.ManyToManyField(
        User, related_name='bookmarks', blank=True)
    total_likes = models.PositiveIntegerField(db_index=True, default=0)

    tags = TaggableManager()

serialiser

class PostSerializer(TaggitSerializer, serializers.ModelSerializer):
    tags = TagListSerializerField()

    class Meta:
        model = Dream
        fields = ('title','user', 'image','description','date_added', 'tags', 'total_likes' )

views


class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.prefetch_related('user').all()
    serializer_class = PostSerializer
    permission_classes = [permissions.IsAuthenticated]

    @action(detail=False, methods=['get'], url_path='current-profile', url_name='current-profile')
    def current_user_posts(self, request):
        # I expected this to add the extra field I required
        # But it does not seem to work as expected
        queryset = self.get_queryset().filter(user=request.user).annotate(
            bookmark=(request.user in "user_bookmark"))

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

Expected behavior when requesting:

{
        "id": 1,
        "tags": [
            "test"
        ],
        "title": "Tets",
        "image": "http://127.0.0.1:8000/media/post_photos/photo1648638314.jpeg",
    
        "description": "TEst",
        "date_added": "2022-05-20T17:47:55.739431Z",
        "total_likes": 0,
        "user": 1,
        "like": true, // true if current user is in user_like, false otherwise
        "bookmark": true // true if current user is in user_bookmark, false otherwise
    }

Actual behavior

TypeError: 'in ' requires string as left operand, not SimpleLazyObject

Edit 1: The answer from here seems to help to resolve the error. Unfortunately, the annotated field does not seem to be returned by the serializer

the edited view:


class PostViewSet(viewsets.ModelViewSet):
    queryset = Post.objects.prefetch_related('user').all()
    serializer_class = PostSerializer
    permission_classes = [permissions.IsAuthenticated]

    @action(detail=False, methods=['get'], url_path='current-profile', url_name='current-profile')
    def current_user_posts(self, request):
        queryset = self.get_queryset().filter(user=request.user).annotate(
            bookmark=Exists(Post.user_bookmark.through.objects.filter(
                post_id=OuterRef('pk'), user_id=request.user.id))
        )

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)



Solution 1:[1]

Job logs in GitLab CI/CD have a limited length. It's designed for operational reasons, as the jobs can create arbitrary outputs so one could - by mistake or by purpose - output even gigabytes or terabytes of text.

But if you scroll up in the output, you have the abillity to view the full logs by pressing 'Complete Raw'.
enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tolis Gerodimos